Browse Source
- Created NotificationSection.vue with complete notification functionality - Updated AccountViewView to use new component via props - Removed notification methods from AccountViewView - Fixed FontAwesome import to use FontAwesomeIcon - Cleaned up unused imports and dependenciespull/150/head
2 changed files with 224 additions and 170 deletions
@ -0,0 +1,212 @@ |
|||||
|
<template> |
||||
|
<section |
||||
|
v-if="isRegistered" |
||||
|
id="sectionNotifications" |
||||
|
class="bg-slate-100 rounded-md overflow-hidden px-4 py-4 mt-8 mb-8" |
||||
|
aria-labelledby="notificationsHeading" |
||||
|
> |
||||
|
<h2 id="notificationsHeading" class="mb-2 font-bold">Notifications</h2> |
||||
|
<div class="flex items-center justify-between"> |
||||
|
<div> |
||||
|
Reminder Notification |
||||
|
<button |
||||
|
class="text-slate-400 fa-fw cursor-pointer" |
||||
|
aria-label="Learn more about reminder notifications" |
||||
|
@click.stop="showReminderNotificationInfo" |
||||
|
> |
||||
|
<font-awesome-icon |
||||
|
icon="question-circle" |
||||
|
aria-hidden="true" |
||||
|
/> |
||||
|
</button> |
||||
|
</div> |
||||
|
<div |
||||
|
class="relative ml-2 cursor-pointer" |
||||
|
role="switch" |
||||
|
:aria-checked="notifyingReminder" |
||||
|
aria-label="Toggle reminder notifications" |
||||
|
tabindex="0" |
||||
|
@click="showReminderNotificationChoice()" |
||||
|
> |
||||
|
<!-- input --> |
||||
|
<input v-model="notifyingReminder" type="checkbox" class="sr-only" /> |
||||
|
<!-- line --> |
||||
|
<div class="block bg-slate-500 w-14 h-8 rounded-full"></div> |
||||
|
<!-- dot --> |
||||
|
<div |
||||
|
class="dot absolute left-1 top-1 bg-slate-400 w-6 h-6 rounded-full transition" |
||||
|
></div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div v-if="notifyingReminder" class="w-full flex justify-between"> |
||||
|
<span class="ml-8 mr-8">Message: "{{ notifyingReminderMessage }}"</span> |
||||
|
<span>{{ notifyingReminderTime.replace(" ", " ") }}</span> |
||||
|
</div> |
||||
|
<div class="mt-2 flex items-center justify-between"> |
||||
|
<!-- label --> |
||||
|
<div> |
||||
|
New Activity Notification |
||||
|
<font-awesome-icon |
||||
|
icon="question-circle" |
||||
|
class="text-slate-400 fa-fw cursor-pointer" |
||||
|
@click.stop="showNewActivityNotificationInfo" |
||||
|
/> |
||||
|
</div> |
||||
|
<!-- toggle --> |
||||
|
<div |
||||
|
class="relative ml-2 cursor-pointer" |
||||
|
@click="showNewActivityNotificationChoice()" |
||||
|
> |
||||
|
<!-- input --> |
||||
|
<input v-model="notifyingNewActivity" type="checkbox" class="sr-only" /> |
||||
|
<!-- line --> |
||||
|
<div class="block bg-slate-500 w-14 h-8 rounded-full"></div> |
||||
|
<!-- dot --> |
||||
|
<div |
||||
|
class="dot absolute left-1 top-1 bg-slate-400 w-6 h-6 rounded-full transition" |
||||
|
></div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div v-if="notifyingNewActivityTime" class="w-full text-right"> |
||||
|
{{ notifyingNewActivityTime.replace(" ", " ") }} |
||||
|
</div> |
||||
|
<div class="mt-2 text-center"> |
||||
|
<router-link class="text-sm text-blue-500" to="/help-notifications"> |
||||
|
Troubleshoot your notifications… |
||||
|
</router-link> |
||||
|
</div> |
||||
|
</section> |
||||
|
<PushNotificationPermission ref="pushNotificationPermission" /> |
||||
|
</template> |
||||
|
|
||||
|
<script lang="ts"> |
||||
|
import { Component, Vue } from "vue-facing-decorator"; |
||||
|
import { Router } from "vue-router"; |
||||
|
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; |
||||
|
import PushNotificationPermission from "./PushNotificationPermission.vue"; |
||||
|
import { createNotifyHelpers } from "@/utils/notify"; |
||||
|
import { ACCOUNT_VIEW_CONSTANTS } from "@/constants/accountView"; |
||||
|
import { DAILY_CHECK_TITLE, DIRECT_PUSH_TITLE } from "@/libs/util"; |
||||
|
import { NotificationIface } from "@/constants/app"; |
||||
|
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin"; |
||||
|
|
||||
|
/** |
||||
|
* NotificationSection.vue - Extracted notification management component |
||||
|
* |
||||
|
* This component handles all notification-related functionality including: |
||||
|
* - Reminder notifications with custom messages |
||||
|
* - New activity notifications |
||||
|
* - Notification permission management |
||||
|
* - Help and troubleshooting links |
||||
|
* |
||||
|
* @author Matthew Raymer |
||||
|
* @component NotificationSection |
||||
|
* @vue-facing-decorator |
||||
|
*/ |
||||
|
@Component({ |
||||
|
components: { |
||||
|
FontAwesomeIcon, |
||||
|
PushNotificationPermission, |
||||
|
}, |
||||
|
mixins: [PlatformServiceMixin], |
||||
|
}) |
||||
|
export default class NotificationSection extends Vue { |
||||
|
$notify!: (notification: NotificationIface, timeout?: number) => void; |
||||
|
$router!: Router; |
||||
|
|
||||
|
// Props |
||||
|
isRegistered: boolean = false; |
||||
|
notifyingNewActivity: boolean = false; |
||||
|
notifyingNewActivityTime: string = ""; |
||||
|
notifyingReminder: boolean = false; |
||||
|
notifyingReminderMessage: string = ""; |
||||
|
notifyingReminderTime: string = ""; |
||||
|
|
||||
|
private notify!: ReturnType<typeof createNotifyHelpers>; |
||||
|
|
||||
|
created() { |
||||
|
this.notify = createNotifyHelpers(this.$notify); |
||||
|
} |
||||
|
|
||||
|
async showNewActivityNotificationInfo(): Promise<void> { |
||||
|
this.notify.confirm( |
||||
|
ACCOUNT_VIEW_CONSTANTS.NOTIFICATIONS.NEW_ACTIVITY_INFO, |
||||
|
async () => { |
||||
|
await (this.$router as Router).push({ |
||||
|
name: "help-notification-types", |
||||
|
}); |
||||
|
}, |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
async showNewActivityNotificationChoice(): Promise<void> { |
||||
|
if (!this.notifyingNewActivity) { |
||||
|
( |
||||
|
this.$refs.pushNotificationPermission as PushNotificationPermission |
||||
|
).open(DAILY_CHECK_TITLE, async (success: boolean, timeText: string) => { |
||||
|
if (success) { |
||||
|
await this.$saveSettings({ |
||||
|
notifyingNewActivityTime: timeText, |
||||
|
}); |
||||
|
this.notifyingNewActivity = true; |
||||
|
this.notifyingNewActivityTime = timeText; |
||||
|
} |
||||
|
}); |
||||
|
} else { |
||||
|
this.notify.notificationOff(DAILY_CHECK_TITLE, async (success) => { |
||||
|
if (success) { |
||||
|
await this.$saveSettings({ |
||||
|
notifyingNewActivityTime: "", |
||||
|
}); |
||||
|
this.notifyingNewActivity = false; |
||||
|
this.notifyingNewActivityTime = ""; |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async showReminderNotificationInfo(): Promise<void> { |
||||
|
this.notify.confirm( |
||||
|
ACCOUNT_VIEW_CONSTANTS.NOTIFICATIONS.REMINDER_INFO, |
||||
|
async () => { |
||||
|
await (this.$router as Router).push({ |
||||
|
name: "help-notification-types", |
||||
|
}); |
||||
|
}, |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
async showReminderNotificationChoice(): Promise<void> { |
||||
|
if (!this.notifyingReminder) { |
||||
|
( |
||||
|
this.$refs.pushNotificationPermission as PushNotificationPermission |
||||
|
).open( |
||||
|
DIRECT_PUSH_TITLE, |
||||
|
async (success: boolean, timeText: string, message?: string) => { |
||||
|
if (success) { |
||||
|
await this.$saveSettings({ |
||||
|
notifyingReminderMessage: message, |
||||
|
notifyingReminderTime: timeText, |
||||
|
}); |
||||
|
this.notifyingReminder = true; |
||||
|
this.notifyingReminderMessage = message || ""; |
||||
|
this.notifyingReminderTime = timeText; |
||||
|
} |
||||
|
}, |
||||
|
); |
||||
|
} else { |
||||
|
this.notify.notificationOff(DIRECT_PUSH_TITLE, async (success) => { |
||||
|
if (success) { |
||||
|
await this.$saveSettings({ |
||||
|
notifyingReminderMessage: "", |
||||
|
notifyingReminderTime: "", |
||||
|
}); |
||||
|
this.notifyingReminder = false; |
||||
|
this.notifyingReminderMessage = ""; |
||||
|
this.notifyingReminderTime = ""; |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
Loading…
Reference in new issue