mirror of
https://github.com/nagaoo0/HabbitGrid.git
synced 2026-04-19 15:23:16 +00:00
Update for Sally
Added Freeze Day
This commit is contained in:
@@ -1,6 +1,21 @@
|
||||
import React from 'react';
|
||||
// Utility to lighten a hex color
|
||||
function lightenColor(hex, percent) {
|
||||
hex = hex.replace(/^#/, '');
|
||||
if (hex.length === 3) hex = hex.split('').map(x => x + x).join('');
|
||||
const num = parseInt(hex, 16);
|
||||
let r = (num >> 16) + Math.round(255 * percent);
|
||||
let g = ((num >> 8) & 0x00FF) + Math.round(255 * percent);
|
||||
let b = (num & 0x0000FF) + Math.round(255 * percent);
|
||||
r = Math.min(255, r);
|
||||
g = Math.min(255, g);
|
||||
b = Math.min(255, b);
|
||||
return `rgb(${r},${g},${b})`;
|
||||
}
|
||||
import { Flame } from 'lucide-react';
|
||||
import { motion } from 'framer-motion';
|
||||
import { getColorIntensity, isToday, formatDate } from '../lib/utils-habit';
|
||||
import { getFrozenDays } from '../lib/utils-habit';
|
||||
import { toggleCompletion } from '../lib/storage';
|
||||
|
||||
const MiniGrid = ({ habit, onUpdate }) => {
|
||||
@@ -31,35 +46,46 @@ const MiniGrid = ({ habit, onUpdate }) => {
|
||||
|
||||
return (
|
||||
<div ref={scrollRef} className="flex gap-1 overflow-x-auto grid-scroll pb-2">
|
||||
{days.map((date, index) => {
|
||||
const dateStr = formatDate(date);
|
||||
const isCompleted = habit.completions.includes(dateStr);
|
||||
const intensity = isCompleted ? getColorIntensity(habit.completions, dateStr) : 0;
|
||||
const isTodayCell = isToday(date);
|
||||
const dayLetter = date.toLocaleDateString('en-US', { weekday: 'short' })[0];
|
||||
|
||||
return (
|
||||
<div key={index} className="flex flex-col items-center">
|
||||
<motion.button
|
||||
whileHover={{ scale: 0.9 }}
|
||||
whileTap={{ scale: 0.5 }}
|
||||
onClick={(e) => handleCellClick(e, date)}
|
||||
className={`habit-cell flex w-8 h-8 transition-all ${isTodayCell ? 'rounded-md' : 'rounded-2xl'}`}
|
||||
style={{
|
||||
backgroundColor: isCompleted
|
||||
? habit.color
|
||||
: 'transparent',
|
||||
opacity: isCompleted ? 0.3 + (intensity * 0.7) : 1,
|
||||
border: isTodayCell
|
||||
? `2px solid ${habit.color}`
|
||||
: `1px solid ${habit.color}20`,
|
||||
}}
|
||||
title={dateStr}
|
||||
/>
|
||||
<span className="text-[10px] text-muted-foreground mt-1">{dayLetter}</span>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
{(() => {
|
||||
const frozenDays = getFrozenDays(habit.completions);
|
||||
return days.map((date, index) => {
|
||||
const dateStr = formatDate(date);
|
||||
const isCompleted = habit.completions.includes(dateStr);
|
||||
const intensity = isCompleted ? getColorIntensity(habit.completions, dateStr) : 0;
|
||||
const isTodayCell = isToday(date);
|
||||
const dayLetter = date.toLocaleDateString('en-US', { weekday: 'short' })[0];
|
||||
const isFrozen = frozenDays.includes(dateStr);
|
||||
return (
|
||||
<div key={index} className="flex flex-col items-center">
|
||||
<motion.button
|
||||
whileHover={{ scale: 0.9 }}
|
||||
whileTap={{ scale: 0.5 }}
|
||||
onClick={(e) => handleCellClick(e, date)}
|
||||
className={`habit-cell flex w-8 h-8 transition-all items-center justify-center ${isTodayCell ? 'rounded-md' : 'rounded-2xl'}`}
|
||||
style={{
|
||||
backgroundColor: isCompleted
|
||||
? habit.color
|
||||
: 'transparent',
|
||||
opacity: isCompleted ? 0.3 + (intensity * 0.7) : 1,
|
||||
border: isTodayCell
|
||||
? `2px solid ${habit.color}`
|
||||
: `1px solid ${habit.color}20`,
|
||||
}}
|
||||
title={dateStr}
|
||||
>
|
||||
{isFrozen && (
|
||||
<span role="img" aria-label="Frozen" style={{ fontSize: '1.2em' }}>❄️</span>
|
||||
)}
|
||||
{/* Flame icon for full streak days */}
|
||||
{isCompleted && intensity >= 1 && (
|
||||
<Flame className="w-5 h-5 absolute" style={{ color: lightenColor(habit.color, 0.4) }} />
|
||||
)}
|
||||
</motion.button>
|
||||
<span className="text-[10px] text-muted-foreground mt-1">{dayLetter}</span>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
})()}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user