gregorian-ethiopian-datepicker
Version:
A React date picker component supporting both Gregorian and Ethiopian calendars
115 lines (114 loc) • 7.96 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var react_1 = __importDefault(require("react"));
var conversion_1 = require("../../utils/conversion");
var CalendarView = function (_a) {
var currentDate = _a.currentDate, onDateSelect = _a.onDateSelect, calendarType = _a.calendarType, minDate = _a.minDate, maxDate = _a.maxDate;
var _b = react_1.default.useState(currentDate.getMonth()), currentMonth = _b[0], setCurrentMonth = _b[1];
var _c = react_1.default.useState(currentDate.getFullYear()), currentYear = _c[0], setCurrentYear = _c[1];
// Handle month/year navigation
var navigateMonth = function (direction) {
var newMonth = currentMonth + direction;
var newYear = currentYear;
if (newMonth > 11) {
newMonth = 0;
newYear++;
}
else if (newMonth < 0) {
newMonth = 11;
newYear--;
}
setCurrentMonth(newMonth);
setCurrentYear(newYear);
};
var navigateYear = function (direction) {
setCurrentYear(currentYear + direction);
};
// Generate days for the current month
var generateDays = function () {
var days = [];
var firstDay = new Date(currentYear, currentMonth, 1).getDay();
var daysInMonth = new Date(currentYear, currentMonth + 1, 0).getDate();
// Previous month days
var prevMonthDays = new Date(currentYear, currentMonth, 0).getDate();
for (var i = firstDay - 1; i >= 0; i--) {
days.push({
day: prevMonthDays - i,
isCurrentMonth: false,
date: new Date(currentYear, currentMonth - 1, prevMonthDays - i)
});
}
// Current month days
for (var i = 1; i <= daysInMonth; i++) {
days.push({
day: i,
isCurrentMonth: true,
date: new Date(currentYear, currentMonth, i)
});
}
// Next month days
var remainingDays = 42 - days.length;
for (var i = 1; i <= remainingDays; i++) {
days.push({
day: i,
isCurrentMonth: false,
date: new Date(currentYear, currentMonth + 1, i)
});
}
return days;
};
// Handle date selection
var handleDateClick = function (date) {
onDateSelect(date);
};
// Check if date is disabled
var isDateDisabled = function (date) {
if (minDate && date < minDate)
return true;
if (maxDate && date > maxDate)
return true;
return false;
};
// Convert to Ethiopian if needed
var renderDay = function (day, isCurrentMonth, date) {
if (calendarType === 'ethiopian') {
var _a = (0, conversion_1.gregorianToEthiopian)(date), ethYear = _a[0], ethMonth = _a[1], ethDay = _a[2];
return "".concat(ethDay);
}
return "".concat(day);
};
var days = generateDays();
var monthNames = calendarType === 'gregorian'
? ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
: ['Meskerem', 'Tikimit', 'Hidar', 'Tahesas', 'Tir', 'Yekatit', 'Megabit', 'Miazia', 'Genbot', 'Sene', 'Hamle', 'Nehase', 'Pagume'];
return (react_1.default.createElement("div", { className: "w-full max-w-xs sm:max-w-md bg-white rounded-lg shadow-lg p-4" },
react_1.default.createElement("div", { className: "flex justify-between items-center mb-4" },
react_1.default.createElement("button", { onClick: function () { return navigateYear(-1); }, className: "p-2 rounded-full hover:bg-gray-100 transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-blue-500", "aria-label": "Previous year" },
react_1.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5 text-gray-600", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor" },
react_1.default.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M11 19l-7-7 7-7m8 14l-7-7 7-7" }))),
react_1.default.createElement("button", { onClick: function () { return navigateMonth(-1); }, className: "p-2 rounded-full hover:bg-gray-100 transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-blue-500", "aria-label": "Previous month" },
react_1.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5 text-gray-600", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor" },
react_1.default.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 19l-7-7 7-7" }))),
react_1.default.createElement("div", { className: "font-semibold text-gray-800 text-lg" },
monthNames[currentMonth],
" ",
currentYear),
react_1.default.createElement("button", { onClick: function () { return navigateMonth(1); }, className: "p-2 rounded-full hover:bg-gray-100 transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-blue-500", "aria-label": "Next month" },
react_1.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5 text-gray-600", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor" },
react_1.default.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5l7 7-7 7" }))),
react_1.default.createElement("button", { onClick: function () { return navigateYear(1); }, className: "p-2 rounded-full hover:bg-gray-100 transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-blue-500", "aria-label": "Next year" },
react_1.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5 text-gray-600", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor" },
react_1.default.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M13 5l7 7-7 7M5 5l7 7-7 7" })))),
react_1.default.createElement("div", { className: "grid grid-cols-7 gap-1 mb-2" }, ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'].map(function (day) { return (react_1.default.createElement("div", { key: day, className: "text-center font-medium text-sm py-2 text-gray-500" }, day.substring(0, 2))); })),
react_1.default.createElement("div", { className: "grid grid-cols-7 gap-1" }, days.map(function (_a, index) {
var day = _a.day, isCurrentMonth = _a.isCurrentMonth, date = _a.date;
var isDisabled = isDateDisabled(date);
var isSelected = date.toDateString() === currentDate.toDateString();
var isToday = new Date().toDateString() === date.toDateString();
return (react_1.default.createElement("button", { key: index, onClick: function () { return !isDisabled && handleDateClick(date); }, disabled: isDisabled, className: "p-2 rounded-full text-center text-sm transition-colors duration-200\n ".concat(isCurrentMonth ? 'text-gray-800' : 'text-gray-400', " \n ").concat(isSelected ? 'bg-blue-600 text-white font-medium' : '', "\n ").concat(isToday && !isSelected ? 'border border-blue-500' : '', "\n ").concat(isDisabled ? 'opacity-40 cursor-not-allowed' : 'hover:bg-gray-100', "\n focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2\n "), "aria-label": "Select ".concat(date.toLocaleDateString()) }, renderDay(day, isCurrentMonth, date)));
}))));
};
exports.default = CalendarView;