feat: DateRange example

master
Guillermo Pages 5 months ago
parent bc2c3b5474
commit c22918d3ea

@ -1,7 +1,7 @@
version: '3.9' version: '3.9'
services: services:
biblio-stats-react: react:
container_name: ${REVERSE_DOMAIN} container_name: ${REVERSE_DOMAIN}
image: "${DOCKER_IMAGE}" image: "${DOCKER_IMAGE}"
labels: labels:

@ -2,6 +2,7 @@ import React from 'react';
import { DateRangePicker } from './examples/DateRangePicker'; import { DateRangePicker } from './examples/DateRangePicker';
import { SingleMonth } from './examples/SingleMonth'; import { SingleMonth } from './examples/SingleMonth';
import { WeekView } from './examples/WeekView'; import { WeekView } from './examples/WeekView';
import { DateRangeView } from './examples/DateRangeView';
import { CompactYear } from './examples/CompactYear'; import { CompactYear } from './examples/CompactYear';
import styles from './App.module.scss'; import styles from './App.module.scss';
@ -11,6 +12,7 @@ const App: React.FC = () => {
<DateRangePicker /> <DateRangePicker />
<SingleMonth /> <SingleMonth />
<WeekView /> <WeekView />
<DateRangeView />
<CompactYear /> <CompactYear />
</div> </div>
); );

@ -0,0 +1,46 @@
@use '../shared/variables' as shared;
@use '../shared/colors' as colors;
.DateRange {
&__Container {
display: flex;
flex-wrap: wrap;
gap: 0;
align-items: flex-start;
}
&__DayWrapper {
padding: shared.$week-wrapper-padding;
@media (min-width: shared.$breakpoint-tablet) {
padding: shared.$week-wrapper-padding-desktop;
}
&--rangeStart:not(&--rangeEnd) {
padding: shared.$week-wrapper-padding 0 shared.$week-wrapper-padding shared.$week-wrapper-padding;
background-color: colors.$day-color-selected;
@media (min-width: shared.$breakpoint-tablet) {
padding: shared.$week-wrapper-padding-desktop 0 shared.$week-wrapper-padding-desktop shared.$week-wrapper-padding-desktop;
}
}
&--rangeEnd:not(&--rangeStart) {
padding: shared.$week-wrapper-padding shared.$week-wrapper-padding shared.$week-wrapper-padding 0;
background-color: colors.$day-color-selected;
@media (min-width: shared.$breakpoint-tablet) {
padding: shared.$week-wrapper-padding-desktop shared.$week-wrapper-padding-desktop shared.$week-wrapper-padding-desktop 0;
}
}
&--selected:not(&--rangeStart):not(&--rangeEnd) {
padding: shared.$week-wrapper-padding 0;
background-color: colors.$day-color-selected;
@media (min-width: shared.$breakpoint-tablet) {
padding: shared.$week-wrapper-padding-desktop 0;
}
}
}
}

@ -0,0 +1,73 @@
import React from 'react';
import { eachDayOfInterval, startOfDay } from 'date-fns';
import { Day } from '../Day';
import { getDateVariations } from '../../../utils/dateUtils';
import { HeaderStyle, DaySize } from '../../../types/calendar';
import styles from './DateRange.module.scss';
import classNames from 'classnames';
interface DateRangeProps {
from: Date;
to: Date;
included?: boolean;
headerStyle?: HeaderStyle;
weekendDays?: number[];
size?: DaySize;
fontProportion?: number;
magnify?: boolean;
}
export const DateRange: React.FC<DateRangeProps> = ({
from,
to,
included = true,
headerStyle = 'tiny',
weekendDays = [6, 0],
size = 'l',
fontProportion = 100,
magnify = false
}) => {
const startDate = startOfDay(from);
const endDate = startOfDay(to);
const days = eachDayOfInterval({ start: startDate, end: endDate });
const dateRange = included ? {
startDate,
endDate,
selecting: false,
hoverDate: null,
anchorDate: null
} : undefined;
return (
<div className={styles.DateRange__Container}>
{days.map((date, i) => {
const dayOfWeek = date.getDay();
const variations = getDateVariations(date, dateRange, weekendDays, dayOfWeek);
const wrapperClasses = classNames(
styles.DateRange__DayWrapper,
{
[styles['DateRange__DayWrapper--rangeStart']]: variations.includes('rangeStart'),
[styles['DateRange__DayWrapper--rangeEnd']]: variations.includes('rangeEnd'),
[styles['DateRange__DayWrapper--selected']]: variations.includes('selected'),
}
);
return (
<div className={wrapperClasses} key={date.toISOString()}>
<Day
date={date}
headerStyle={headerStyle}
variations={variations}
size={size}
fontProportion={fontProportion}
magnify={magnify}
/>
</div>
);
})}
</div>
);
};

@ -0,0 +1,68 @@
import React, { useState } from 'react';
import { DateRange } from '../components/calendar/DateRange';
import { Controls } from '../components/calendar/Controls';
import { HeaderStyle, DaySize, MonthCutoffType } from '../types/calendar';
import styles from './Examples.module.scss';
export const DateRangeView: React.FC = () => {
const [dayHeaderStyle, setDayHeaderStyle] = useState<HeaderStyle>('tiny');
const [size, setSize] = useState<DaySize>('l');
const [fontProportion, setFontProportion] = useState<number>(100);
const [included, setIncluded] = useState<boolean>(true);
const [monthCutoff, setMonthCutoff] = useState<MonthCutoffType>(undefined);
const fromDate = new Date(2025, 0, 15); // January 15, 2025
const toDate = new Date(2025, 0, 22); // January 22, 2025
return (
<section className={styles.section}>
<h2 className={styles.sectionTitle}>Date Range View</h2>
<p className={styles.sectionDescription}>
Display a custom date range with optional selection highlighting.
</p>
<Controls
headerStyle={dayHeaderStyle}
monthCutoff={monthCutoff}
size={size}
fontProportion={fontProportion}
onHeaderStyleChange={setDayHeaderStyle}
onMonthCutoffChange={setMonthCutoff}
onSizeChange={setSize}
onFontProportionChange={setFontProportion}
/>
<div className={styles.controlRow}>
<label className={styles.control}>
<input
type="checkbox"
checked={included}
onChange={(e) => setIncluded(e.target.checked)}
/>
<span>Show as selected range</span>
</label>
</div>
<div className={styles.demoContainer}>
<DateRange
from={fromDate}
to={toDate}
included={included}
headerStyle={dayHeaderStyle}
weekendDays={[6, 0]}
size={size}
fontProportion={fontProportion}
magnify={true}
/>
</div>
<div className={styles.codeExample}>
<pre>{`<DateRange
from={new Date(2025, 0, 15)}
to={new Date(2025, 0, 22)}
included={${included}}
headerStyle="${dayHeaderStyle}"
size="${size}"
fontProportion={${fontProportion}}
magnify={true}
/>`}</pre>
</div>
</section>
);
};
Loading…
Cancel
Save