forked from jsnbuchanan/crowd-funder-for-time-pwa
refactor(push-notification): use native time input and polish notification UI
PushNotificationPermission: - Swap hour/minute number inputs and AM/PM toggle for native <input type="time"> - Add timeValue computed to keep existing hour/minute/AM-PM state in sync - Remove unused checkHourInput and checkMinuteInput - Tighten copy and layout: headings, labels, char count, button spacing AccountViewView: - Show reminder time and message in a bordered box with Time/Message labels - Adjust spacing in notifications section
This commit is contained in:
@@ -14,64 +14,54 @@
|
||||
<div
|
||||
class="flex w-11/12 max-w-sm mx-auto mb-3 overflow-hidden bg-white rounded-lg shadow-lg"
|
||||
>
|
||||
<div class="w-full px-6 py-6 text-slate-900 text-center">
|
||||
<p v-if="isSystemReady" class="text-lg mb-4">
|
||||
<div class="w-full px-6 py-6 text-slate-900">
|
||||
<h1 v-if="isSystemReady" class="text-center font-bold mb-4">
|
||||
<span v-if="isDailyCheck">
|
||||
Would you like to be notified of new activity, up to once a day?
|
||||
</span>
|
||||
<span v-else>
|
||||
Would you like to get a reminder message once a day?
|
||||
</span>
|
||||
</p>
|
||||
<p v-else class="text-lg mb-4">
|
||||
</h1>
|
||||
<h1 v-else class="text-center font-bold mb-4">
|
||||
{{ waitingMessage }}
|
||||
<font-awesome icon="spinner" spin />
|
||||
</p>
|
||||
</h1>
|
||||
|
||||
<div v-if="canShowNotificationForm">
|
||||
<div v-if="isDailyCheck">
|
||||
<span>Yes, send me a message when there is new data for me</span>
|
||||
<span
|
||||
><b>Yes</b>, send me a message when there is new data for
|
||||
me</span
|
||||
>
|
||||
</div>
|
||||
<div v-else>
|
||||
<span>Yes, send me this message:</span>
|
||||
<span class="text-slate-500 text-sm font-bold"
|
||||
>Send me this message:</span
|
||||
>
|
||||
<!-- eslint-disable -->
|
||||
<textarea
|
||||
type="text"
|
||||
id="push-message"
|
||||
v-model="messageInput"
|
||||
class="rounded border border-slate-400 mt-2 px-2 py-2 w-full"
|
||||
class="rounded border border-slate-400 mt-2 p-2 w-full"
|
||||
maxlength="100"
|
||||
></textarea
|
||||
>
|
||||
<!-- eslint-enable -->
|
||||
<span class="w-full flex justify-between text-xs text-slate-500">
|
||||
<span></span>
|
||||
<div class="text-xs text-slate-500">
|
||||
<span>(100 characters max)</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span class="flex flex-row justify-center">
|
||||
<span class="mt-2">... at: </span>
|
||||
<input
|
||||
v-model="hourInput"
|
||||
type="number"
|
||||
class="rounded-l border border-r-0 border-slate-400 ml-2 mt-2 px-2 py-2 text-center w-20"
|
||||
@change="checkHourInput"
|
||||
/>
|
||||
<input
|
||||
v-model="minuteInput"
|
||||
type="number"
|
||||
class="border border-slate-400 mt-2 px-2 py-2 text-center w-20"
|
||||
@change="checkMinuteInput"
|
||||
/>
|
||||
<span
|
||||
class="rounded-r border border-slate-400 bg-slate-200 text-center text-blue-500 mt-2 px-2 py-2 w-20"
|
||||
@click="toggleHourAm"
|
||||
>
|
||||
<span>{{ amPmLabel }} <font-awesome :icon="amPmIcon" /></span>
|
||||
</span>
|
||||
</span>
|
||||
<div class="mt-2 mb-4 flex items-center gap-2">
|
||||
<label for="time" class="text-slate-500 text-sm font-bold">At this time:</label>
|
||||
<input
|
||||
v-model="timeValue"
|
||||
type="time"
|
||||
id="time"
|
||||
class="!px-4 !py-4 text-md bg-white border border-slate-400 rounded"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
class="block w-full text-center text-md font-bold uppercase bg-blue-600 text-white mt-2 px-2 py-2 rounded-md"
|
||||
@@ -82,7 +72,7 @@
|
||||
</div>
|
||||
|
||||
<button
|
||||
class="block w-full text-center text-md font-bold uppercase bg-slate-600 text-white mt-4 px-2 py-2 rounded-md"
|
||||
class="block w-full text-center text-md font-bold uppercase bg-slate-600 text-white mt-2 px-2 py-2 rounded-md"
|
||||
@click="close()"
|
||||
>
|
||||
No, Not Now
|
||||
@@ -393,36 +383,6 @@ export default class PushNotificationPermission extends Vue {
|
||||
);
|
||||
}
|
||||
|
||||
private checkHourInput() {
|
||||
const hourNum = parseInt(this.hourInput);
|
||||
if (isNaN(hourNum)) {
|
||||
this.hourInput = "12";
|
||||
} else if (hourNum < 1) {
|
||||
this.hourInput = "12";
|
||||
this.hourAm = !this.hourAm;
|
||||
} else if (hourNum > 12) {
|
||||
this.hourInput = "1";
|
||||
this.hourAm = !this.hourAm;
|
||||
} else {
|
||||
this.hourInput = hourNum.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private checkMinuteInput() {
|
||||
const minuteNum = parseInt(this.minuteInput);
|
||||
if (isNaN(minuteNum)) {
|
||||
this.minuteInput = "00";
|
||||
} else if (minuteNum < 0) {
|
||||
this.minuteInput = "59";
|
||||
} else if (minuteNum < 10) {
|
||||
this.minuteInput = "0" + minuteNum;
|
||||
} else if (minuteNum > 59) {
|
||||
this.minuteInput = "00";
|
||||
} else {
|
||||
this.minuteInput = minuteNum.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private async turnOnNotifications() {
|
||||
let notifyCloser = () => {};
|
||||
return this.askPermission()
|
||||
@@ -655,6 +615,27 @@ export default class PushNotificationPermission extends Vue {
|
||||
return `${this.hourInput}:${this.minuteInput} ${this.hourAm ? "AM" : "PM"}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Two-way binding for native time input (HH:mm 24h).
|
||||
* Syncs with hourInput, minuteInput, and hourAm.
|
||||
*/
|
||||
get timeValue(): string {
|
||||
return this.convertTo24HourFormat();
|
||||
}
|
||||
set timeValue(value: string) {
|
||||
const [h = "0", m = "0"] = value.split(":");
|
||||
const hour24 = parseInt(h, 10);
|
||||
const minute = parseInt(m, 10);
|
||||
this.minuteInput = minute.toString().padStart(2, "0");
|
||||
if (hour24 >= 12) {
|
||||
this.hourAm = false;
|
||||
this.hourInput = hour24 === 12 ? "12" : (hour24 - 12).toString();
|
||||
} else {
|
||||
this.hourAm = true;
|
||||
this.hourInput = hour24 === 0 ? "12" : hour24.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the AM/PM state for the hour input
|
||||
*/
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
aria-labelledby="notificationsHeading"
|
||||
>
|
||||
<h2 id="notificationsHeading" class="mb-2 font-bold">Notifications</h2>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<div>
|
||||
Reminder Notification
|
||||
<button
|
||||
@@ -124,11 +124,15 @@
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="notifyingReminder" class="w-full">
|
||||
<div class="flex justify-between mb-2">
|
||||
<span class="ml-8 mr-8"
|
||||
>Message: "{{ notifyingReminderMessage }}"</span
|
||||
>
|
||||
<span>{{ notifyingReminderTime.replace(" ", " ") }}</span>
|
||||
<div
|
||||
class="text-sm text-slate-500 mb-2 bg-white rounded px-3 py-2 border border-slate-200"
|
||||
>
|
||||
<div>
|
||||
<b>Time:</b> {{ notifyingReminderTime.replace(" ", " ") }}
|
||||
</div>
|
||||
<div>
|
||||
<b>Message:</b> <i>"{{ notifyingReminderMessage }}"</i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-2 text-center">
|
||||
<button
|
||||
@@ -139,7 +143,7 @@
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="false" class="mt-2 flex items-center justify-between">
|
||||
<div v-if="false" class="mt-4 flex items-center justify-between">
|
||||
<!-- label -->
|
||||
<div>
|
||||
New Activity Notification
|
||||
|
||||
Reference in New Issue
Block a user