refactor NotificationSetting component to use SettingsLayout; remove NotificationSettings wrapper

This commit is contained in:
Mo Tarbin
2025-09-20 18:45:40 -04:00
parent ac767f63ae
commit a5a90dfbdd
2 changed files with 320 additions and 327 deletions

View File

@@ -25,6 +25,7 @@ import {
UpdateNotificationTarget, UpdateNotificationTarget,
UpdateUserDetails, UpdateUserDetails,
} from '../../utils/Fetcher' } from '../../utils/Fetcher'
import SettingsLayout from './SettingsLayout'
const NotificationSetting = () => { const NotificationSetting = () => {
const { showWarning } = useNotification() const { showWarning } = useNotification()
@@ -134,330 +135,334 @@ const NotificationSetting = () => {
}) })
} }
return ( return (
<div className='grid gap-4 py-4' id='notifications'> <SettingsLayout title='Notification Settings'>
<Typography level='h3'>Device Notification</Typography> <div className='grid gap-4 py-4' id='notifications'>
<Divider /> <Typography level='h3'>Device Notification</Typography>
<Typography level='body-md'>Manage your Device Notificaiton</Typography> <Divider />
<Typography level='body-md'>Manage your Device Notificaiton</Typography>
<FormControl orientation='horizontal'> <FormControl orientation='horizontal'>
<Switch <Switch
disabled={!Capacitor.isNativePlatform()} disabled={!Capacitor.isNativePlatform()}
checked={deviceNotification} checked={deviceNotification}
onClick={event => { onClick={event => {
event.preventDefault() event.preventDefault()
if (deviceNotification === false) { if (deviceNotification === false) {
LocalNotifications.requestPermissions().then(resp => { LocalNotifications.requestPermissions().then(resp => {
if (resp.display === 'granted') { if (resp.display === 'granted') {
setDeviceNotification(true) setDeviceNotification(true)
setNotificationPreferences({ granted: true }) setNotificationPreferences({ granted: true })
} else if (resp.display === 'denied') { } else if (resp.display === 'denied') {
showWarning({ showWarning({
title: 'Notification Permission Denied', title: 'Notification Permission Denied',
message: message:
'You have denied notification permissions. You can enable them later in your device settings.', 'You have denied notification permissions. You can enable them later in your device settings.',
}) })
setDeviceNotification(false) setDeviceNotification(false)
setNotificationPreferences({ granted: false }) setNotificationPreferences({ granted: false })
} }
})
} else {
setDeviceNotification(false)
}
}}
color={deviceNotification ? 'success' : 'neutral'}
variant={deviceNotification ? 'solid' : 'outlined'}
slotProps={{
endDecorator: {
sx: {
minWidth: 24,
},
},
}}
sx={{ mr: 2 }}
/>
<div>
<FormLabel>Device Notification</FormLabel>
<FormHelperText sx={{ mt: 0 }}>
{Capacitor.isNativePlatform()
? 'Receive notification on your device when a task is due'
: 'This feature is only available on mobile devices'}{' '}
</FormHelperText>
</div>
</FormControl>
{deviceNotification && (
<Card>
{[
{
title: 'Due Date Notification',
checked: dueNotification,
set: setDueNotification,
label: 'Notification when the task is due',
property: 'dueNotification',
disabled: false,
},
{
title: 'Pre-Due Date Notification',
checked: preDueNotification,
set: setPreDueNotification,
label: 'Notification a few hours before the task is due',
property: 'preDueNotification',
disabled: false,
},
{
title: 'Overdue Notification',
checked: naggingNotification,
set: setNaggingNotification,
label: 'Notification when the task is overdue',
property: 'naggingNotification',
disabled: false,
},
].map(item => (
<FormControl
key={item.property}
orientation='horizontal'
sx={{ width: 385, justifyContent: 'space-between' }}
>
<div>
<FormLabel>{item.title}</FormLabel>
<FormHelperText sx={{ mt: 0 }}>{item.label} </FormHelperText>
</div>
<Switch
checked={item.checked}
disabled={item.disabled}
onClick={() => {
setNotificationPreferences({ [item.property]: !item.checked })
item.set(!item.checked)
}}
color={item.checked ? 'success' : ''}
variant='solid'
endDecorator={item.checked ? 'On' : 'Off'}
slotProps={{ endDecorator: { sx: { minWidth: 24 } } }}
/>
</FormControl>
))}
</Card>
)}
<FormControl
orientation='horizontal'
sx={{ width: 400, justifyContent: 'space-between' }}
>
<div>
<FormLabel>Push Notifications</FormLabel>
<FormHelperText sx={{ mt: 0 }}>
{Capacitor.isNativePlatform()
? 'Receive Nudges, Announcements, and Chore Assignments via Push Notifications'
: 'This feature is only available on mobile devices'}{' '}
</FormHelperText>
</div>
<Switch
disabled={!Capacitor.isNativePlatform()}
checked={pushNotification}
onClick={async event => {
event.preventDefault()
if (pushNotification === false) {
try {
const resp = await PushNotifications.requestPermissions()
console.log('user PushNotifications permission', resp)
if (resp.receive === 'granted') {
setPushNotification(true)
setPushNotificationPreferences({ granted: true })
// Register push notifications after permission is granted
await registerPushNotifications()
}
if (resp.receive !== 'granted') {
showWarning({
title: 'Push Notification Permission Denied',
message:
'Push notifications have been disabled. You can enable them in your device settings if needed.',
})
setPushNotification(false)
setPushNotificationPreferences({ granted: false })
console.log('User denied permission', resp)
}
} catch (error) {
console.error('Error setting up push notifications:', error)
}
} else {
setPushNotification(false)
}
}}
color={pushNotification ? 'success' : 'neutral'}
variant={pushNotification ? 'solid' : 'outlined'}
endDecorator={pushNotification ? 'On' : 'Off'}
slotProps={{
endDecorator: {
sx: {
minWidth: 24,
},
},
}}
/>
</FormControl>
<Button
variant='soft'
color='primary'
sx={{
width: '210px',
mb: 1,
}}
onClick={() => {
// schedule a local notification in 5 seconds
LocalNotifications.schedule({
notifications: [
{
title: 'Task Reminder',
body: 'You have a task due soon',
id: 1,
schedule: { at: new Date(Date.now() + 3000) },
sound: null,
attachments: null,
actionTypeId: '',
extra: null,
},
],
})
}}
>
Test Notification{' '}
</Button>
<Typography level='h3'>Custom Notification</Typography>
<Divider />
<Typography level='body-md'>
Notificaiton through other platform like Telegram or Pushover
</Typography>
<FormControl orientation='horizontal'>
<Switch
checked={Boolean(chatID !== 0)}
onClick={event => {
event.preventDefault()
if (chatID !== 0) {
setChatID(0)
} else {
setChatID('')
UpdateUserDetails({
chatID: Number(0),
}).then(resp => {
resp.json().then(data => {
refetchUserProfile()
}) })
}) } else {
} setDeviceNotification(false)
setNotificationTarget('0') }
handleSave() }}
}} color={deviceNotification ? 'success' : 'neutral'}
color={chatID !== 0 ? 'success' : 'neutral'} variant={deviceNotification ? 'solid' : 'outlined'}
variant={chatID !== 0 ? 'solid' : 'outlined'} slotProps={{
slotProps={{ endDecorator: {
endDecorator: { sx: {
sx: { minWidth: 24,
minWidth: 24, },
}, },
}, }}
}} sx={{ mr: 2 }}
sx={{ mr: 2 }} />
/> <div>
<div> <FormLabel>Device Notification</FormLabel>
<FormLabel>Custom Notification</FormLabel> <FormHelperText sx={{ mt: 0 }}>
<FormHelperText sx={{ mt: 0 }}> {Capacitor.isNativePlatform()
Receive notification on other platform ? 'Receive notification on your device when a task is due'
</FormHelperText> : 'This feature is only available on mobile devices'}{' '}
</div> </FormHelperText>
</FormControl> </div>
{chatID !== 0 && ( </FormControl>
<Box {deviceNotification && (
<Card>
{[
{
title: 'Due Date Notification',
checked: dueNotification,
set: setDueNotification,
label: 'Notification when the task is due',
property: 'dueNotification',
disabled: false,
},
{
title: 'Pre-Due Date Notification',
checked: preDueNotification,
set: setPreDueNotification,
label: 'Notification a few hours before the task is due',
property: 'preDueNotification',
disabled: false,
},
{
title: 'Overdue Notification',
checked: naggingNotification,
set: setNaggingNotification,
label: 'Notification when the task is overdue',
property: 'naggingNotification',
disabled: false,
},
].map(item => (
<FormControl
key={item.property}
orientation='horizontal'
sx={{ width: 385, justifyContent: 'space-between' }}
>
<div>
<FormLabel>{item.title}</FormLabel>
<FormHelperText sx={{ mt: 0 }}>{item.label} </FormHelperText>
</div>
<Switch
checked={item.checked}
disabled={item.disabled}
onClick={() => {
setNotificationPreferences({
[item.property]: !item.checked,
})
item.set(!item.checked)
}}
color={item.checked ? 'success' : ''}
variant='solid'
endDecorator={item.checked ? 'On' : 'Off'}
slotProps={{ endDecorator: { sx: { minWidth: 24 } } }}
/>
</FormControl>
))}
</Card>
)}
<FormControl
orientation='horizontal'
sx={{ width: 400, justifyContent: 'space-between' }}
>
<div>
<FormLabel>Push Notifications</FormLabel>
<FormHelperText sx={{ mt: 0 }}>
{Capacitor.isNativePlatform()
? 'Receive Nudges, Announcements, and Chore Assignments via Push Notifications'
: 'This feature is only available on mobile devices'}{' '}
</FormHelperText>
</div>
<Switch
disabled={!Capacitor.isNativePlatform()}
checked={pushNotification}
onClick={async event => {
event.preventDefault()
if (pushNotification === false) {
try {
const resp = await PushNotifications.requestPermissions()
console.log('user PushNotifications permission', resp)
if (resp.receive === 'granted') {
setPushNotification(true)
setPushNotificationPreferences({ granted: true })
// Register push notifications after permission is granted
await registerPushNotifications()
}
if (resp.receive !== 'granted') {
showWarning({
title: 'Push Notification Permission Denied',
message:
'Push notifications have been disabled. You can enable them in your device settings if needed.',
})
setPushNotification(false)
setPushNotificationPreferences({ granted: false })
console.log('User denied permission', resp)
}
} catch (error) {
console.error('Error setting up push notifications:', error)
}
} else {
setPushNotification(false)
}
}}
color={pushNotification ? 'success' : 'neutral'}
variant={pushNotification ? 'solid' : 'outlined'}
endDecorator={pushNotification ? 'On' : 'Off'}
slotProps={{
endDecorator: {
sx: {
minWidth: 24,
},
},
}}
/>
</FormControl>
<Button
variant='soft'
color='primary'
sx={{ sx={{
display: 'flex', width: '210px',
flexDirection: 'column', mb: 1,
gap: 2, }}
onClick={() => {
// schedule a local notification in 5 seconds
LocalNotifications.schedule({
notifications: [
{
title: 'Task Reminder',
body: 'You have a task due soon',
id: 1,
schedule: { at: new Date(Date.now() + 3000) },
sound: null,
attachments: null,
actionTypeId: '',
extra: null,
},
],
})
}} }}
> >
<Select Test Notification{' '}
value={notificationTarget} </Button>
sx={{ maxWidth: '200px' }} <Typography level='h3'>Custom Notification</Typography>
onChange={(e, selected) => setNotificationTarget(selected)} <Divider />
> <Typography level='body-md'>
<Option value='0'>None</Option> Notificaiton through other platform like Telegram or Pushover
<Option value='1'>Telegram</Option> </Typography>
<Option value='2'>Pushover</Option>
<Option value='3'>Webhooks</Option>
</Select>
{notificationTarget === '1' && (
<>
<Typography level='body-xs'>
You need to initiate a message to the bot in order for the
Telegram notification to work{' '}
<a
style={{
textDecoration: 'underline',
color: '#0891b2',
}}
href='https://t.me/DonetickBot'
>
Click here
</a>{' '}
to start a chat
</Typography>
<Typography level='body-sm'>Chat ID</Typography> <FormControl orientation='horizontal'>
<Switch
<Input checked={Boolean(chatID !== 0)}
value={chatID} onClick={event => {
onChange={e => setChatID(e.target.value)} event.preventDefault()
placeholder='User ID / Chat ID' if (chatID !== 0) {
sx={{ setChatID(0)
width: '200px', } else {
}} setChatID('')
/> UpdateUserDetails({
<Typography mt={0} level='body-xs'> chatID: Number(0),
If you don't know your Chat ID, start chat with userinfobot and }).then(resp => {
it will send you your Chat ID.{' '} resp.json().then(data => {
<a refetchUserProfile()
style={{ })
textDecoration: 'underline', })
color: '#0891b2', }
}} setNotificationTarget('0')
href='https://t.me/userinfobot' handleSave()
> }}
Click here color={chatID !== 0 ? 'success' : 'neutral'}
</a>{' '} variant={chatID !== 0 ? 'solid' : 'outlined'}
to start chat with userinfobot{' '} slotProps={{
</Typography> endDecorator: {
</> sx: {
)} minWidth: 24,
{notificationTarget === '2' && ( },
<> },
<Typography level='body-sm'>User key</Typography> }}
<Input sx={{ mr: 2 }}
value={chatID} />
onChange={e => setChatID(e.target.value)} <div>
placeholder='User ID' <FormLabel>Custom Notification</FormLabel>
sx={{ <FormHelperText sx={{ mt: 0 }}>
width: '200px', Receive notification on other platform
}} </FormHelperText>
/> </div>
</> </FormControl>
)} {chatID !== 0 && (
{error && ( <Box
<Typography color='warning' level='body-sm'> sx={{
{error} display: 'flex',
</Typography> flexDirection: 'column',
)} gap: 2,
<Button
sx={{
width: '110px',
mb: 1,
}} }}
onClick={handleSave}
> >
Save <Select
</Button> value={notificationTarget}
</Box> sx={{ maxWidth: '200px' }}
)} onChange={(e, selected) => setNotificationTarget(selected)}
</div> >
<Option value='0'>None</Option>
<Option value='1'>Telegram</Option>
<Option value='2'>Pushover</Option>
<Option value='3'>Webhooks</Option>
</Select>
{notificationTarget === '1' && (
<>
<Typography level='body-xs'>
You need to initiate a message to the bot in order for the
Telegram notification to work{' '}
<a
style={{
textDecoration: 'underline',
color: '#0891b2',
}}
href='https://t.me/DonetickBot'
>
Click here
</a>{' '}
to start a chat
</Typography>
<Typography level='body-sm'>Chat ID</Typography>
<Input
value={chatID}
onChange={e => setChatID(e.target.value)}
placeholder='User ID / Chat ID'
sx={{
width: '200px',
}}
/>
<Typography mt={0} level='body-xs'>
If you don't know your Chat ID, start chat with userinfobot
and it will send you your Chat ID.{' '}
<a
style={{
textDecoration: 'underline',
color: '#0891b2',
}}
href='https://t.me/userinfobot'
>
Click here
</a>{' '}
to start chat with userinfobot{' '}
</Typography>
</>
)}
{notificationTarget === '2' && (
<>
<Typography level='body-sm'>User key</Typography>
<Input
value={chatID}
onChange={e => setChatID(e.target.value)}
placeholder='User ID'
sx={{
width: '200px',
}}
/>
</>
)}
{error && (
<Typography color='warning' level='body-sm'>
{error}
</Typography>
)}
<Button
sx={{
width: '110px',
mb: 1,
}}
onClick={handleSave}
>
Save
</Button>
</Box>
)}
</div>
</SettingsLayout>
) )
} }

View File

@@ -1,12 +0,0 @@
import NotificationSetting from './NotificationSetting'
import SettingsLayout from './SettingsLayout'
const NotificationSettings = () => {
return (
<SettingsLayout title="Notification Settings">
<NotificationSetting />
</SettingsLayout>
)
}
export default NotificationSettings