mirror of
https://github.com/nagaoo0/HabbitGrid.git
synced 2026-01-12 07:54:53 +00:00
Add random congrats msg
This commit is contained in:
@@ -17,6 +17,7 @@ import { motion } from 'framer-motion';
|
||||
import { getColorIntensity, isToday, formatDate } from '../lib/utils-habit';
|
||||
import { getFrozenDays } from '../lib/utils-habit';
|
||||
import { toggleCompletion } from '../lib/storage';
|
||||
import { toast } from './ui/use-toast';
|
||||
|
||||
const MiniGrid = ({ habit, onUpdate }) => {
|
||||
const today = new Date();
|
||||
@@ -39,10 +40,33 @@ const MiniGrid = ({ habit, onUpdate }) => {
|
||||
days.push(date);
|
||||
}
|
||||
|
||||
const handleCellClick = (e, date) => {
|
||||
const handleCellClick = async (e, date) => {
|
||||
e.stopPropagation();
|
||||
toggleCompletion(habit.id, formatDate(date));
|
||||
const dateStr = formatDate(date);
|
||||
const isTodayCell = isToday(date);
|
||||
const wasCompleted = habit.completions.includes(dateStr);
|
||||
toggleCompletion(habit.id, dateStr);
|
||||
onUpdate();
|
||||
// Only show encouragement toast if validating (adding) today's dot
|
||||
if (isTodayCell && !wasCompleted) {
|
||||
try {
|
||||
const res = await fetch('/encouragements.json');
|
||||
const messages = await res.json();
|
||||
const msg = messages[Math.floor(Math.random() * messages.length)];
|
||||
toast({
|
||||
title: '🎉 Keep Going!',
|
||||
description: msg,
|
||||
duration: 2500,
|
||||
});
|
||||
} catch (err) {
|
||||
// fallback message
|
||||
toast({
|
||||
title: '🎉 Keep Going!',
|
||||
description: 'Great job! Keep up the streak!',
|
||||
duration: 2500,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -7,19 +7,21 @@ import React from 'react';
|
||||
const ToastProvider = ToastPrimitives.Provider;
|
||||
|
||||
const ToastViewport = React.forwardRef(({ className, ...props }, ref) => (
|
||||
<ToastPrimitives.Viewport
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
<ToastPrimitives.Viewport
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'fixed z-[100] flex max-h-screen w-full flex-col-reverse p-4',
|
||||
'sm:bottom-4 sm:right-4 sm:top-auto sm:left-auto sm:flex-col md:max-w-[420px]',
|
||||
'bottom-4 left-1/2 transform -translate-x-1/2 sm:transform-none',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
ToastViewport.displayName = ToastPrimitives.Viewport.displayName;
|
||||
|
||||
const toastVariants = cva(
|
||||
'data-[swipe=move]:transition-none group relative pointer-events-auto flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full data-[state=closed]:slide-out-to-right-full',
|
||||
'data-[swipe=move]:transition-none group relative pointer-events-auto flex w-full items-center justify-between space-x-4 overflow-hidden rounded-2xl border-0 p-6 pr-8 shadow-2xl transition-all bg-white/80 backdrop-blur-lg ring-2 ring-green-300/40 drop-shadow-xl scale-95 animate-toast-in data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=open]:slide-in-from-bottom-full data-[state=closed]:slide-out-to-right-full',
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
@@ -73,20 +75,24 @@ const ToastClose = React.forwardRef(({ className, ...props }, ref) => (
|
||||
ToastClose.displayName = ToastPrimitives.Close.displayName;
|
||||
|
||||
const ToastTitle = React.forwardRef(({ className, ...props }, ref) => (
|
||||
<ToastPrimitives.Title
|
||||
ref={ref}
|
||||
className={cn('text-sm font-semibold', className)}
|
||||
{...props}
|
||||
/>
|
||||
<ToastPrimitives.Title
|
||||
ref={ref}
|
||||
className={cn('text-lg font-bold flex items-center gap-2', className)}
|
||||
{...props}
|
||||
>
|
||||
<span className="animate-float inline-block">🎊</span> {props.children}
|
||||
</ToastPrimitives.Title>
|
||||
));
|
||||
ToastTitle.displayName = ToastPrimitives.Title.displayName;
|
||||
|
||||
const ToastDescription = React.forwardRef(({ className, ...props }, ref) => (
|
||||
<ToastPrimitives.Description
|
||||
ref={ref}
|
||||
className={cn('text-sm opacity-90', className)}
|
||||
{...props}
|
||||
/>
|
||||
<ToastPrimitives.Description
|
||||
ref={ref}
|
||||
className={cn('text-base opacity-95 font-medium flex items-center gap-2', className)}
|
||||
{...props}
|
||||
>
|
||||
<span className="animate-float inline-block">✨</span> {props.children}
|
||||
</ToastPrimitives.Description>
|
||||
));
|
||||
ToastDescription.displayName = ToastPrimitives.Description.displayName;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user