File size: 5,942 Bytes
0f8617c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import { useState } from 'react';
import { Calendar as CalendarIcon, ChevronLeft, ChevronRight, Check, X } from 'lucide-react';

const SmartCalendar = ({ availability = [], bookings = [], onToggleDate }) => {
    const [currentDate, setCurrentDate] = useState(new Date());

    const daysInMonth = (year, month) => new Date(year, month + 1, 0).getDate();
    const firstDayOfMonth = (year, month) => new Date(year, month, 1).getDay();

    const year = currentDate.getFullYear();
    const month = currentDate.getMonth();

    const monthNames = [
        "January", "February", "March", "April", "May", "June",
        "July", "August", "September", "October", "November", "December"
    ];

    const prevMonth = () => setCurrentDate(new Date(year, month - 1, 1));
    const nextMonth = () => setCurrentDate(new Date(year, month + 1, 1));

    const days = [];
    const totalDays = daysInMonth(year, month);
    const startDay = firstDayOfMonth(year, month);

    // Padding for previous month
    for (let i = 0; i < startDay; i++) {
        days.push({ day: null, fullDate: null });
    }

    // Current month days
    for (let i = 1; i <= totalDays; i++) {
        const fullDate = new Date(year, month, i).toISOString().split('T')[0];
        const isAvailable = availability.includes(fullDate);
        const dayBookings = bookings.filter(b => b.date.startsWith(fullDate));
        days.push({ day: i, fullDate, isAvailable, bookings: dayBookings });
    }

    return (
        <div className="bg-white rounded-[2rem] border border-gray-100 shadow-sm overflow-hidden animate-in fade-in duration-500">
            <div className="p-6 bg-gray-50/50 border-b border-gray-50 flex items-center justify-between">
                <div className="flex items-center space-x-3">
                    <div className="bg-blue-600 p-2 rounded-xl text-white">
                        <CalendarIcon size={18} />
                    </div>
                    <h3 className="font-black text-gray-900 tracking-tight">{monthNames[month]} {year}</h3>
                </div>
                <div className="flex items-center space-x-2">
                    <button onClick={prevMonth} className="p-2 hover:bg-gray-200 rounded-xl transition text-gray-400 hover:text-gray-900">
                        <ChevronLeft size={20} />
                    </button>
                    <button onClick={nextMonth} className="p-2 hover:bg-gray-200 rounded-xl transition text-gray-400 hover:text-gray-900">
                        <ChevronRight size={20} />
                    </button>
                </div>
            </div>

            <div className="p-4">
                <div className="grid grid-cols-7 gap-1 mb-4">
                    {['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'].map(d => (
                        <div key={d} className="text-center text-[10px] font-black text-gray-400 uppercase tracking-widest py-2">
                            {d}
                        </div>
                    ))}

                    {days.map((d, i) => (
                        <div
                            key={i}
                            onClick={() => d.fullDate && onToggleDate(d.fullDate)}
                            className={`
                                relative aspect-square flex flex-col items-center justify-center rounded-2xl cursor-pointer transition-all duration-300 group
                                ${!d.day ? 'pointer-events-none' : 'hover:scale-95'}
                                ${d.isAvailable ? 'bg-blue-50 text-blue-700 border border-blue-100' : 'text-gray-900 hover:bg-gray-50'}
                                ${d.bookings.length > 0 ? 'ring-2 ring-indigo-600 ring-offset-2' : ''}
                            `}
                        >
                            <span className="text-sm font-bold z-10">{d.day}</span>

                            {d.day && (
                                <>
                                    <div className="absolute top-1 right-1 opacity-0 group-hover:opacity-100 transition-opacity">
                                        {d.isAvailable ? <X size={10} className="text-red-400" /> : <Check size={10} className="text-green-400" />}
                                    </div>
                                    {d.bookings.length > 0 && (
                                        <div className="absolute bottom-2 w-1.5 h-1.5 bg-indigo-600 rounded-full shadow-lg shadow-indigo-100"></div>
                                    )}
                                    {d.isAvailable && !d.bookings.length && (
                                        <div className="absolute inset-0 bg-blue-100/50 rounded-2xl animate-pulse"></div>
                                    )}
                                </>
                            )}
                        </div>
                    ))}
                </div>

                <div className="mt-6 pt-6 border-t border-gray-50 flex items-center justify-between px-2">
                    <div className="flex items-center space-x-4">
                        <div className="flex items-center space-x-2">
                            <div className="w-3 h-3 bg-blue-50 border border-blue-100 rounded-sm"></div>
                            <span className="text-[10px] font-black uppercase text-gray-400 tracking-wider">Available</span>
                        </div>
                        <div className="flex items-center space-x-2">
                            <div className="w-3 h-3 bg-indigo-600 rounded-full"></div>
                            <span className="text-[10px] font-black uppercase text-gray-400 tracking-wider">Booked</span>
                        </div>
                    </div>
                    <p className="text-[9px] font-bold text-gray-300 italic italic">Click a date to toggle</p>
                </div>
            </div>
        </div>
    );
};

export default SmartCalendar;