Quarter and Year View
Usage
theme="ios" You can turn auto theming on and let it decide based on the platform.
Usage
themeVariant="light" You can turn auto dark mode on based on system settings.
Usage
touchUi={true}
// touch interaction is enabled Use touch interaction on mobile or pointer interaction on desktop.
Usage
locale={localeEn} Selecting the locale loads the localized settings and the translated UI text.
Quarter and Year View
Create a calendar with quarter views that can be navigated quarter by quarter or switch to a year view on the fly. Show any relevant information with labels or add background colors to days along with week counters.
Demo
Code
View code on GitHub
import {
CalendarNav,
CalendarNext,
CalendarPrev,
CalendarToday,
Datepicker,
Segmented,
SegmentedGroup,
setOptions ,
} from '@mobiscroll/react';
import { useCallback, useMemo, useState } from 'react';
setOptions({
locale: ,
theme: ' ',
themeVariant: ' '
});
function App() {
const [type, setType] = useState('q4');
const [selectedDate, setDate] = useState(new Date());
const [activeDate, setActiveDate] = useState(new Date());
const calType = useMemo(() => (type === 'year' ? 'year' : 'month'), [type]);
const handleTypeChange = useCallback(
(event) => {
const tp = event.target.value;
const year = activeDate.getFullYear();
let date;
switch (tp) {
case 'q1':
date = new Date(year, 0, 1);
break;
case 'q2':
date = new Date(year, 3, 1);
break;
case 'q3':
date = new Date(year, 6, 1);
break;
case 'q4':
date = new Date(year, 9, 1);
break;
case 'year':
date = new Date(year, activeDate.getMonth(), 1);
break;
default:
break;
}
setType(tp);
setDate(date);
setActiveDate(date);
},
[activeDate],
);
const handlePageChange = useCallback(
(event) => {
let t = '';
if (type === 'year') {
t = 'year';
} else {
const month = event.firstDay.getMonth();
if (month < 3) {
t = 'q1';
} else if (month < 6) {
t = 'q2';
} else if (month < 9) {
t = 'q3';
} else {
t = 'q4';
}
}
setTimeout(() => {
setActiveDate(event.firstDay);
setType(t);
});
},
[type],
);
const handleDateChange = useCallback((event) => {
setDate(event.value);
}, []);
const calendarHeaderSwitch = useCallback(
() => (
<>
<CalendarNav />
<div className="quarter-year-header-picker">
<SegmentedGroup value={type} onChange={handleTypeChange}>
<Segmented value="q1">Q1</Segmented>
<Segmented value="q2">Q2</Segmented>
<Segmented value="q3">Q3</Segmented>
<Segmented value="q4">Q4</Segmented>
<Segmented value="year">Year</Segmented>
</SegmentedGroup>
</div>
<CalendarPrev />
<CalendarToday />
<CalendarNext />
</>
),
[handleTypeChange, type],
);
return (
<Datepicker
display="inline"
calendarType={calType}
calendarSize={3}
refDate="1970-01-01"
renderCalendarHeader={calendarHeaderSwitch}
onPageChange={handlePageChange}
onChange={handleDateChange}
showWeekNumbers={true}
value={selectedDate}
/>
);
}
export default App;
import {
CalendarNav,
CalendarNext,
CalendarPrev,
CalendarToday,
Datepicker,
MbscDatepickerChangeEvent,
MbscDatepickerPageChangeEvent,
Segmented,
SegmentedGroup,
setOptions ,
} from '@mobiscroll/react';
import { ChangeEvent, FC, useCallback, useMemo, useState } from 'react';
setOptions({
locale: ,
theme: ' ',
themeVariant: ' '
});
const App: FC = () => {
const [type, setType] = useState<string>('q4');
const calType = useMemo<'year' | 'month' | 'week' | undefined>(() => (type === 'year' ? 'year' : 'month'), [type]);
const [selectedDate, setDate] = useState<Date>(new Date());
const [activeDate, setActiveDate] = useState<Date>(new Date());
const handleTypeChange = useCallback(
(event: ChangeEvent<HTMLInputElement>) => {
const tp = event.target.value;
const year = activeDate.getFullYear();
let date;
switch (tp) {
case 'q1':
date = new Date(year, 0, 1);
break;
case 'q2':
date = new Date(year, 3, 1);
break;
case 'q3':
date = new Date(year, 6, 1);
break;
case 'q4':
date = new Date(year, 9, 1);
break;
case 'year':
date = new Date(year, activeDate.getMonth(), 1);
break;
default:
break;
}
setType(tp);
setDate(date!);
setActiveDate(date!);
},
[activeDate],
);
const handlePageChange = useCallback(
(event: MbscDatepickerPageChangeEvent) => {
let t = '';
if (type === 'year') {
t = 'year';
} else {
const month = event.firstDay.getMonth();
if (month < 3) {
t = 'q1';
} else if (month < 6) {
t = 'q2';
} else if (month < 9) {
t = 'q3';
} else {
t = 'q4';
}
}
setTimeout(() => {
setActiveDate(event.firstDay);
setType(t);
});
},
[type],
);
const handleDateChange = useCallback((event: MbscDatepickerChangeEvent) => {
setDate(new Date(event.value as string));
}, []);
const calendarHeaderSwitch = useCallback(
() => (
<>
<CalendarNav />
<div className="quarter-year-header-picker">
<SegmentedGroup value={type} onChange={handleTypeChange}>
<Segmented value="q1">Q1</Segmented>
<Segmented value="q2">Q2</Segmented>
<Segmented value="q3">Q3</Segmented>
<Segmented value="q4">Q4</Segmented>
<Segmented value="year">Year</Segmented>
</SegmentedGroup>
</div>
<CalendarPrev />
<CalendarToday />
<CalendarNext />
</>
),
[handleTypeChange, type],
);
return (
<Datepicker
controls={['calendar']}
display="inline"
calendarType={calType}
calendarSize={3}
refDate="1970-01-01"
renderCalendarHeader={calendarHeaderSwitch}
onPageChange={handlePageChange}
onChange={handleDateChange}
showWeekNumbers={true}
value={selectedDate}
/>
);
};
export default App;
.mbsc-datepicker .quarter-year-header-picker .mbsc-segmented {
max-width: 280px;
margin: 0 auto;
}
.quarter-year-header-picker {
flex: 1 0 auto;
}