Feature: Dynamic time-of-day specific positive reinforcement notifications
This commit is contained in:
parent
3a31c8a956
commit
95f0d94411
@ -11,6 +11,69 @@ if (process.env.NEXT_PUBLIC_VAPID_PUBLIC_KEY && process.env.VAPID_PRIVATE_KEY) {
|
||||
);
|
||||
}
|
||||
|
||||
const MESSAGES = {
|
||||
morning: [
|
||||
"Rise and shine! Today is a perfect day to stay on track.",
|
||||
"New morning, new strength. Let's keep that streak alive!",
|
||||
"Success starts with your first choice today. You've got this!",
|
||||
"Your morning check-in starts now. Every smoke-free minute counts!",
|
||||
"The morning is yours. Claim it by logging your progress.",
|
||||
"Small steps lead to big changes. Start your day by logging in!"
|
||||
],
|
||||
afternoon: [
|
||||
"Keep the momentum going! You're doing great this afternoon.",
|
||||
"Halfway through the day and looking strong. Log your progress!",
|
||||
"The afternoon slump is no match for your willpower. Stay focused!",
|
||||
"Just checking in—how's your journey going? Log it now!",
|
||||
"You're stronger than any craving. Keep pushing forward!",
|
||||
"Consistency is key to mastery. You’re doing amazing today!"
|
||||
],
|
||||
evening: [
|
||||
"Wind down with a win. Another day closer to your goal!",
|
||||
"Evening reflection: You faced the day and won. Log your success!",
|
||||
"Don't let the evening cravings win. You're almost there!",
|
||||
"Sweet dreams are made of smoke-free days. Keep it up!",
|
||||
"The night is calm, and so are you. Finish the day strong!",
|
||||
"Final check-in for the day! Log your progress and sleep proud.",
|
||||
"Progress isn't always linear, but you're showing up. Great job!",
|
||||
"You survived another day. Celebrate with a quick log!"
|
||||
]
|
||||
};
|
||||
|
||||
function getNotificationData(timeStr: string) {
|
||||
// timeStr is HH:MM
|
||||
const [h, m] = timeStr.split(':').map(Number);
|
||||
const totalMinutes = h * 60 + m;
|
||||
|
||||
let category: 'morning' | 'afternoon' | 'evening';
|
||||
|
||||
// Morning: 5:30 (330m) - 11:00 (660m)
|
||||
// Afternoon: 11:00 (660m) - 16:30 (990m)
|
||||
// Evening: 16:30 (990m) - 5:30 (330m)
|
||||
|
||||
if (totalMinutes >= 330 && totalMinutes < 660) {
|
||||
category = 'morning';
|
||||
} else if (totalMinutes >= 660 && totalMinutes < 990) {
|
||||
category = 'afternoon';
|
||||
} else {
|
||||
category = 'evening';
|
||||
}
|
||||
|
||||
const options = MESSAGES[category];
|
||||
const message = options[Math.floor(Math.random() * options.length)];
|
||||
|
||||
const titles = [
|
||||
"QuitTraq Motivation",
|
||||
"QuitTraq Milestone",
|
||||
"QuitTraq Strength",
|
||||
"QuitTraq Journey",
|
||||
"QuitTraq Check-in"
|
||||
];
|
||||
const title = titles[Math.floor(Math.random() * titles.length)];
|
||||
|
||||
return { title, message };
|
||||
}
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
// Protect with a secret if configured
|
||||
@ -37,6 +100,7 @@ export async function GET(request: NextRequest) {
|
||||
|
||||
let shouldSend = false;
|
||||
let notificationBody = '';
|
||||
let notificationTitle = '';
|
||||
let tag = '';
|
||||
|
||||
if (user.frequency === 'hourly') {
|
||||
@ -52,7 +116,9 @@ export async function GET(request: NextRequest) {
|
||||
if (userTimeString >= startStr && userTimeString <= endStr && currentM === startM) {
|
||||
if (user.lastNotifiedDate !== currentHourKey) {
|
||||
shouldSend = true;
|
||||
notificationBody = "How are you doing? Log your status to stay on track!";
|
||||
const { title: t, message } = getNotificationData(userTimeString);
|
||||
notificationBody = message;
|
||||
notificationTitle = t;
|
||||
tag = 'hourly-reminder';
|
||||
|
||||
// Update to match current Hour Key so we don't send again this hour
|
||||
@ -69,7 +135,9 @@ export async function GET(request: NextRequest) {
|
||||
if (userTimeString === user.reminderTime) {
|
||||
if (user.lastNotifiedDate !== userDateString) {
|
||||
shouldSend = true;
|
||||
notificationBody = "Time to log your daily usage! Every day counts.";
|
||||
const { title: t, message } = getNotificationData(userTimeString);
|
||||
notificationBody = message;
|
||||
notificationTitle = t;
|
||||
tag = 'daily-reminder';
|
||||
|
||||
await updateLastNotifiedD1(user.userId, userDateString);
|
||||
@ -78,9 +146,8 @@ export async function GET(request: NextRequest) {
|
||||
}
|
||||
|
||||
if (shouldSend) {
|
||||
const title = user.frequency === 'hourly' ? 'QuitTraq Hourly Check-in' : 'QuitTraq Reminder';
|
||||
const payload = JSON.stringify({
|
||||
title: title,
|
||||
title: notificationTitle,
|
||||
body: notificationBody,
|
||||
tag: tag,
|
||||
url: '/'
|
||||
|
||||
@ -247,14 +247,14 @@ export function UnifiedQuitPlanCard({
|
||||
if (!showNicotine && !showWeed) return null;
|
||||
|
||||
return (
|
||||
<Card className="backdrop-blur-xl shadow-xl border-white/10 overflow-hidden">
|
||||
<CardHeader className="pb-3 border-b border-white/5 bg-white/5">
|
||||
<CardTitle className="flex items-center gap-2 text-sm sm:text-base font-black uppercase tracking-widest opacity-80">
|
||||
<TrendingDown className="h-5 w-5 text-primary" />
|
||||
<Card className="backdrop-blur-2xl shadow-2xl border-white/10 overflow-hidden bg-white/5">
|
||||
<CardHeader className="pb-1 pt-6 px-4 sm:px-6">
|
||||
<CardTitle className="flex items-center gap-2 text-sm sm:text-base font-black uppercase tracking-widest opacity-60">
|
||||
<TrendingDown className="h-4 w-4 text-primary" />
|
||||
Quit Journey Plan
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="pt-4 p-3 sm:p-6">
|
||||
<CardContent className="pt-2 p-2 sm:p-4">
|
||||
{showNicotine && (
|
||||
<SubstancePlanSection
|
||||
substance="nicotine"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user