Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: calendar component #823

Merged
merged 54 commits into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
c49b425
Merge pull request #783 from Trendyol/next
leventozen Jan 25, 2024
b6d0b51
build: continue if component is not custom element
dilandoogan Apr 4, 2024
d00e308
feat(calendar): calculate calendar days and render calendar component
dilandoogan Mar 31, 2024
b8bb21b
refactor(calendar): changing names to be understandable
dilandoogan Apr 1, 2024
ab82af3
refactor(calendar): review updates
dilandoogan Apr 4, 2024
bad4dba
Merge branch 'next' into calendar
dilandoogan Apr 4, 2024
1de1de3
refactor(calendar): improve excluded files for build
dilandoogan Apr 5, 2024
ce7b1a2
feat(calendar): set months and years view for calendar
dilandoogan Apr 14, 2024
d8fbb22
feat(calendar): trigger event when new date selected
dilandoogan Apr 15, 2024
1c0765c
feat(calendar): add calendar component basic story
dilandoogan Apr 15, 2024
21cef1a
feat(calendar): adding multipe type option for calendar
dilandoogan Apr 16, 2024
2360713
feat(calendar): fix multiple type select view
dilandoogan Apr 16, 2024
8fdb5ec
feat(calendar): disable user to select from disabled dates
dilandoogan Apr 17, 2024
701c7ec
feat(calendar): disable user to select a date before min date or afte…
dilandoogan Apr 17, 2024
de36d9a
Merge branch 'next' into calendar
buseselvi Apr 18, 2024
9718397
Merge remote-tracking branch 'origin/calendar' into calendar
dilandoogan Apr 22, 2024
2d61a72
feat(calendar): show previous month and next month days on calendar
dilandoogan Apr 22, 2024
09e1e65
Merge branch 'next' into calendar
buseselvi Apr 25, 2024
71c176c
feat(calendar): handle disabled dates and min max date properly
dilandoogan Apr 28, 2024
02a82f3
Merge branch 'next' into calendar
dilandoogan Apr 28, 2024
6bedf08
Merge remote-tracking branch 'origin/calendar' into calendar
dilandoogan Apr 28, 2024
5c8b11c
Merge branch 'next' into calendar
dilandoogan May 2, 2024
db3ae96
feat(calendar): changing calendarDate type implementations and first…
dilandoogan May 2, 2024
644d139
Merge branch 'next' into calendar
AykutSarac May 8, 2024
980c4d4
feat(calendar): adding all stories for calendar
dilandoogan May 11, 2024
f47db06
Merge branch 'next' into calendar
buseselvi May 13, 2024
ef348bb
feat(calendar): run prettier
dilandoogan May 13, 2024
615fa60
feat(calendar): design fixes
dilandoogan May 15, 2024
4d82c50
feat(calendar): design fixes and type adding for calendar view and ca…
dilandoogan May 15, 2024
ad79bfd
feat(calendar): change medium button vertical padding
dilandoogan May 15, 2024
83d4816
adding hover class to days
dilandoogan May 19, 2024
c4edfad
feat(calendar): make color white if other month date is selected
dilandoogan May 19, 2024
f0a1800
Merge branch 'next' into calendar
buseselvi May 20, 2024
a7ab20d
feat(calendar): format with prettier
dilandoogan May 20, 2024
0f7b0b4
feat(calendar): dont give hover to disabled dates
dilandoogan May 20, 2024
ec7d7a6
feat(calendar): dont allow cursor on disabled dates
dilandoogan May 20, 2024
f48e99e
remove unused important
dilandoogan May 22, 2024
8c0fbc8
feat(calendar): rendering days as button
dilandoogan Jun 10, 2024
8d41396
Merge branch 'next' into calendar
buseselvi Jun 10, 2024
b243f94
feat(calendar): run prettier
dilandoogan Jun 11, 2024
6cc87d9
feat(calendar): styling fix
dilandoogan Jun 11, 2024
0488ab4
feat(calendar): run prettier
dilandoogan Jun 11, 2024
5206a03
feat(calendar): accesibility fix
dilandoogan Jun 12, 2024
5102bf2
feat(calendar): run prettier
dilandoogan Jun 12, 2024
3a1d76a
feat(calendar): run prettier
dilandoogan Jun 12, 2024
69d7de2
adding --bl-button-focus-border-color color for calendar
dilandoogan Jun 13, 2024
99b270a
self review improvements
dilandoogan Jun 13, 2024
e9549e6
review updates
dilandoogan Jun 13, 2024
bf02254
Update src/components/calendar/bl-calendar.ts
AykutSarac Jun 14, 2024
37734f6
Update src/components/calendar/bl-calendar.ts
AykutSarac Jun 14, 2024
2c3668b
Merge branch 'next' into calendar
AykutSarac Jun 14, 2024
8e64712
review updates
dilandoogan Jun 24, 2024
6e7ac56
selecting disabled dates bug fix
dilandoogan Jun 25, 2024
b7885af
event name fix
dilandoogan Jun 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions playground/template.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,6 @@ <h1>Baklava Playground</h1>
</p>

<bl-button>Baklava is ready</bl-button>
<bl-calendar type="multiple"></bl-calendar>
</body>
</html>
10 changes: 9 additions & 1 deletion src/components/calendar/bl-calendar.constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,15 @@ export const MONTHS: Month[] = [
{ name: "December", value: 11 },
];

export const DAYS: Day[] = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
export const DAYS: Day[] = [
{ value: 0, name: "Sun" },
{ value: 1, name: "Mon" },
{ value: 2, name: "Tue" },
{ value: 3, name: "Wed" },
{ value: 4, name: "Thu" },
{ value: 5, name: "Fri" },
{ value: 6, name: "Sat" },
];

export const FIRST_MONTH_INDEX = 0;
export const LAST_MONTH_INDEX = 11;
200 changes: 94 additions & 106 deletions src/components/calendar/bl-calendar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
CalendarDay,
CalendarType,
CalendarView,
Day,
SelectedDate,
} from "./bl-calendar.types";

Expand All @@ -29,14 +30,14 @@ export default class BlCalendar extends LitElement {
/**
*Defines the minimum date value for the calendar
AykutSarac marked this conversation as resolved.
Show resolved Hide resolved
*/
@property()
minDate: Date;
@property({ attribute: false, reflect: true })
minDate: Date = new Date(2024, 2, 3);

/**
* Defines the maximum date value for the calendar
*/
@property()
maxDate: Date;
@property({ attribute: false, reflect: true })
maxDate: Date = new Date(2024, 5, 3);
ozkersemih marked this conversation as resolved.
Show resolved Hide resolved

/**
* Defines the default selected date value for the calendar
Expand Down Expand Up @@ -74,6 +75,9 @@ export default class BlCalendar extends LitElement {
@state()
private _calendarYears: number[] = [];

@state()
private _calendarDays: Day[] = [];

/**
* Fires when date selection changes
*/
Expand Down Expand Up @@ -132,12 +136,10 @@ export default class BlCalendar extends LitElement {
for (let i = 1; i <= 7; i++) this._calendarYears.push(this._calendarYear + i);
}
}
handleDate(calendarDay: CalendarDay) {
const date = { day: calendarDay.day, month: this._calendarMonth, year: this._calendarYear };

if (calendarDay.belongsToPrevMonth) {
handleDate(date: CalendarDay) {
if (date.month < this._calendarMonth) {
this.setPreviousCalendarView();
} else if (calendarDay.belongsToNextMonth) {
} else if (date.month > this._calendarMonth) {
this.setNextCalendarView();
}

Expand All @@ -164,155 +166,141 @@ export default class BlCalendar extends LitElement {
);
this.requestUpdate();
}
checkIfSelectedDate(day: CalendarDay) {
return this._selectedDates.find(date => {
checkIfSelectedDate(calendarDay: CalendarDay) {
return this._selectedDates.find(selectedDate => {
return (
date.day === day.day &&
date.month === this._calendarMonth &&
date.year === this._calendarYear &&
day.belongsToCurrentMonth
selectedDate.day === calendarDay.day &&
selectedDate.month === this._calendarMonth &&
selectedDate.year === this._calendarYear &&
calendarDay.month === this._calendarMonth
);
});
}
checkIfDateIsToday(day: number) {
checkIfDateIsToday(calendarDay: CalendarDay) {
const today = new Date();

return (
this._calendarMonth === today.getMonth() &&
this._calendarYear === today.getFullYear() &&
day === today.getDate()
today.getMonth() === calendarDay.month &&
today.getFullYear() === calendarDay.year &&
today.getDate() === calendarDay.day
);
}
checkIfDateIsDisabled(day: number) {
const date = new Date(this._calendarYear, this._calendarMonth, day);
checkIfDateIsDisabled(calendarDay: CalendarDay) {
const date = new Date(calendarDay.year, calendarDay.month, calendarDay.day);

if (date < this.minDate || date > this.maxDate) {
return true;
}

if (Array.isArray(this.disabledDates)) {
return this.disabledDates.find(disabledDate => {
return date.toDateString() === disabledDate.toDateString();
});
} else if (this.disabledDates) {
return date.toDateString() === this.disabledDates.toDateString();
} else if (this.minDate && this.maxDate) {
return date < this.minDate || date > this.maxDate;
} else if (this.minDate) {
return date < this.minDate;
} else if (this.maxDate) return date > this.maxDate;
else return false;
if (date.toDateString() === this.disabledDates.toString()) return true;
}
return false;
}

createCalendarDays() {
const currentMonthCalendar: Calendar = new Map();
let dayOfTheWeek = 0; // from sunday
let iteratedDay = 1;
let currentMonthCalendarCellIterator = 0;
const dateAndYear = { month: this._calendarMonth, year: this._calendarYear };
const currentMonthStartWeekDay = this.getWeekDayOfDate(this._calendarYear, this._calendarMonth);
const calendar: Calendar = new Map();

this._calendarDays = DAYS.slice(this.startOfWeek).concat(DAYS.slice(0, this.startOfWeek));

const currentMonthStartWeekDay = this.getWeekDayOfDate(this._calendarYear, this._calendarMonth); // 1

const lastMonthDaysCount =
currentMonthStartWeekDay < this.startOfWeek
? 7 - (this.startOfWeek - currentMonthStartWeekDay)
: currentMonthStartWeekDay - this.startOfWeek;

const previousMonthDayCount = this.getDayNumInAMonth(
this._calendarYear,
this._calendarMonth - 1
);
const currentMonthTotalCalendarCellCount =
this.getDayNumInAMonth(this._calendarYear, this._calendarMonth) + currentMonthStartWeekDay;

const currentMonthDayCount = this.getDayNumInAMonth(this._calendarYear, this._calendarMonth);

let dayOfTheWeek = this.startOfWeek; // from sunday

for (
currentMonthCalendarCellIterator;
currentMonthCalendarCellIterator < currentMonthTotalCalendarCellCount;
currentMonthCalendarCellIterator += 1
let lastMonthDaysIterator = lastMonthDaysCount;
lastMonthDaysIterator > 0;
lastMonthDaysIterator--
) {
const mod = dayOfTheWeek % 7;

if (currentMonthCalendarCellIterator < currentMonthStartWeekDay) {
currentMonthCalendar.set(DAYS[mod], [
{
day:
previousMonthDayCount -
(currentMonthStartWeekDay - currentMonthCalendarCellIterator - 1),
belongsToPrevMonth: true,
...dateAndYear,
},
]);
} else if (currentMonthCalendar.get(DAYS[mod])) {
currentMonthCalendar.get(DAYS[mod])?.push({
day: iteratedDay,
belongsToCurrentMonth: true,
...dateAndYear,
});
iteratedDay += 1;
} else {
currentMonthCalendar.set(DAYS[mod], [
{
day: iteratedDay,
belongsToCurrentMonth: true,
...dateAndYear,
},
]);
iteratedDay += 1;
}
calendar.set(DAYS[mod].name, [
{
day: previousMonthDayCount - lastMonthDaysIterator + 1,
month: this._calendarMonth - 1,
year: this._calendarYear,
},
]);

dayOfTheWeek += 1;
}
let nearestMultipleOfSeven = currentMonthCalendarCellIterator;

if (currentMonthCalendarCellIterator % 7 > 0)
nearestMultipleOfSeven =
currentMonthCalendarCellIterator + (7 - (currentMonthCalendarCellIterator % 7));

for (
let nextMonthDaysIterator = 1;
nextMonthDaysIterator <= nearestMultipleOfSeven - currentMonthCalendarCellIterator;
nextMonthDaysIterator++
let currentMonthDaysIterator = 1;
currentMonthDaysIterator <= currentMonthDayCount;
currentMonthDaysIterator++
) {
const mod = (currentMonthCalendarCellIterator + nextMonthDaysIterator - 1) % 7;

currentMonthCalendar.get(DAYS[mod])?.push({
day: nextMonthDaysIterator,
belongsToNextMonth: true,
...dateAndYear,
});
const mod = dayOfTheWeek % 7;
const day = {
day: currentMonthDaysIterator,
month: this._calendarMonth,
year: this._calendarYear,
};

if (calendar.get(DAYS[mod].name)) {
calendar.get(DAYS[mod].name)?.push(day);
} else {
calendar.set(DAYS[mod].name, [day]);
}
dayOfTheWeek += 1;
}
return currentMonthCalendar;
}
reArrangeCalendarForStartOfWeek(map: Calendar) {
const newMap: Calendar = new Map();
const keys = Array.from(map.keys());
const index = keys.indexOf(DAYS[this.startOfWeek]);

for (let i = 0; i < keys.length; i++) {
const newIndex = (index + i) % keys.length;
const index = this._calendarDays.findIndex(day => day.value === dayOfTheWeek % 7);

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const temp = map.get(keys[newIndex]) as CalendarDay[];
if (index !== 0) {
for (
let nextMonthDaysIterator = 1;
nextMonthDaysIterator <= this._calendarDays.length - index;
nextMonthDaysIterator++
) {
const mod = dayOfTheWeek % 7;
const day = {
day: nextMonthDaysIterator,
month: this._calendarMonth + 1,
year: this._calendarYear,
};

if (!temp[0].belongsToCurrentMonth) {
const firstElement = temp.shift();
calendar.get(DAYS[mod].name)?.push(day);

if (firstElement) temp.push(firstElement);
dayOfTheWeek += 1;
}
newMap.set(DAYS[newIndex], temp);
}

return newMap;
return calendar;
}
render() {
const getCalendarView = (calendarView: CalendarView) => {
if (calendarView === "days") {
const calendarDays = this.createCalendarDays();
const reArrangeCalendarForStartOfWeek = this.reArrangeCalendarForStartOfWeek(calendarDays);

return html`<div class="days-view">
${[...reArrangeCalendarForStartOfWeek.entries()].map(([key, value]) => {
${[...calendarDays.entries()].map(([key, value]) => {
return html` <div class="day-column">
<div class="weekday-text day-cell">${key}</div>
${value.map(date => {
const isSelectedDay = this.checkIfSelectedDate(date);
const isDayToday = this.checkIfDateIsToday(date.day);
const isDisabledDay = this.checkIfDateIsDisabled(date.day);
const isDayToday = this.checkIfDateIsToday(date);
const isDisabledDay = this.checkIfDateIsDisabled(date);

//console.log(isDisabledDay, date);
return html` <div
class="day-cell ${isDayToday && "today-day"} ${isSelectedDay &&
"selected-day"} ${isDisabledDay && "disabled-day"} ${(date.belongsToNextMonth ||
date.belongsToPrevMonth) &&
"other-month-day"}"
"selected-day"} ${isDisabledDay && "disabled-day"} ${date.month !==
this._calendarMonth && "other-month-day"}"
@click="${() => !isDisabledDay && this.handleDate(date)}"
>
${date.day}
Expand Down
8 changes: 4 additions & 4 deletions src/components/calendar/bl-calendar.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,23 @@ type MonthNames =
| "November"
| "December";

type DayNames = "Sun" | "Mon" | "Tue" | "Wed" | "Thu" | "Fri" | "Sat";

export type MonthValues = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11;
export type DayValues = 0 | 1 | 2 | 3 | 4 | 5 | 6;

export type CalendarView = "days" | "months" | "years";

export type CalendarType = "single" | "multiple" | "range";
export type Month = { value: MonthValues; name: MonthNames };
export type Day = string;
export type Day = { value: DayValues; name: DayNames };

export type SelectedDate = { day: number; month: number; year: number };

export type CalendarDay = {
day: number;
month: number;
year: number;
belongsToPrevMonth?: boolean;
belongsToCurrentMonth?: boolean;
belongsToNextMonth?: boolean;
};

export type Calendar = Map<string, CalendarDay[]>;