Factor out common day wrapping logic and week handling

This commit is contained in:
Quantum 2023-07-15 17:54:18 -04:00
parent a8edb3cfab
commit 766a222979
5 changed files with 181 additions and 223 deletions

View file

@ -1,5 +1,14 @@
@import 'bootstrap/scss/variables'; @import 'bootstrap/scss/variables';
@import 'bootstrap/scss/mixins';
@import 'bootstrap/scss/buttons';
@import 'bootstrap/scss/grid';
@import './consts';
.Calendar {
@include make-container();
}
/* Calendar head */
.Calendar-head { .Calendar-head {
display: flex; display: flex;
justify-content: center; justify-content: center;
@ -47,3 +56,68 @@
.Calendar-today-button { .Calendar-today-button {
max-width: 5em; max-width: 5em;
} }
/* Days */
.Month {
margin-left: -$calendar-gutter;
margin-right: -$calendar-gutter;
}
.Month-days {
@include make-row($gutter: 0);
> * {
@include make-col-ready();
}
}
.DayOuter {
padding: $calendar-gutter;
}
.DayFiller {
display: none;
}
.DayOuter {
display: flex;
@include make-col($size: 1, $columns: 2);
}
.Day, .DayFiller {
padding: 0.5em;
border-radius: $border-radius;
}
.Day {
flex: 1;
border: 1px solid black;
}
.DayFiller {
border: 1px solid transparent;
}
.Day-name {
font-size: 2em;
font-weight: 600;
}
.Day-weekday {
font-weight: 600;
}
.Day-today {
background: $gray-300;
}
/* Weekdays */
.Month-weekdayHead {
display: none;
}
.WeekdayName {
text-align: center;
font-weight: 600;
font-size: 1.2em;
}

View file

@ -0,0 +1,50 @@
@import 'bootstrap/scss/variables';
@import 'bootstrap/scss/mixins';
@import 'bootstrap/scss/grid';
@include media-breakpoint-up(sm) {
.DayOuter {
@include make-col($size: 1, $columns: 3);
}
}
@include media-breakpoint-up(md) {
.DayOuter {
@include make-col($size: 1, $columns: 4);
}
}
@include media-breakpoint-up(lg) {
.DayOuter {
@include make-col($size: 1, $columns: 5);
}
}
@include media-breakpoint-up(xl) {
.Month-weekdayHead {
display: block;
@include make-row($gutter: 0);
position: sticky;
top: 0;
background: white;
margin-top: -$spacer * 7.5;
padding-top: $spacer * 7.5;
z-index: 19;
}
.Month-days {
margin-top: $spacer;
}
.DayOuter, .WeekdayName, .DayFiller {
@include make-col($size: 1, $columns: 7);
}
.Day-weekday {
display: none;
}
.DayFiller {
display: block;
}
}

View file

@ -7,112 +7,65 @@
@import '@common/ui/consts.scss'; @import '@common/ui/consts.scss';
@import '@common/ui/MonthBasedCalendar.scss'; @import '@common/ui/MonthBasedCalendar.scss';
.Calendar { @include media-breakpoint-up(xs) {
@include make-container(); .DayOuter.NormalDay {
} @include make-col($size: 1, $columns: 2);
}
.Month-decadeHead { .DayOuter.ComplementaryDay {
display: none; @include make-col($size: 1, $columns: 1);
}
.Month-decade {
@include make-row($gutter: 0);
> * {
@include make-col-ready();
} }
} }
.Month-decadeSplitter-small, .Month-decadeSplitter-medium { @include media-breakpoint-up(sm) {
width: 100%; .DayOuter.NormalDay {
} @include make-col($size: 1, $columns: 3);
}
.Month-decadeSplitter-medium {
display: none;
} }
@include media-breakpoint-up(md) { @include media-breakpoint-up(md) {
.Month-decadeSplitter-small { .DayOuter.NormalDay {
display: none; @include make-col($size: 1, $columns: 4);
}
}
@include media-breakpoint-up(lg) {
.DayOuter.NormalDay {
@include make-col($size: 1, $columns: 6);
} }
.Month-decadeSplitter-medium { .DayOuter.ComplementaryDay {
display: block; @include make-col($size: 1, $columns: 2);
} }
} }
@include media-breakpoint-up(xl) { @include media-breakpoint-up(xl) {
.Month-decadeSplitter-medium { .DayOuter.NormalDay {
display: none; @include make-col($size: 1, $columns: 8);
} }
}
.Month-decadeHead { @include media-breakpoint-up(xxl) {
.Month-weekdayHead {
display: block; display: block;
@include make-row($gutter: 0); @include make-row($gutter: 0);
position: sticky;
top: 0;
background: white;
margin-top: -$spacer * 7.5;
padding-top: $spacer * 7.5;
z-index: 19;
} }
.Day-decade { .Month-days {
margin-top: $spacer;
}
.DayOuter.NormalDay, .WeekdayName {
@include make-col($size: 1, $columns: 10);
}
.Day-weekday {
display: none; display: none;
} }
} }
.Day, .DecadeName, .ComplementaryDay-fake {
margin: $calendar-gutter;
@include make-col($columns: 10);
}
@include media-breakpoint-up(lg) {
.ComplementaryDays {
@include make-row($gutter: 0);
> * {
@include make-col-ready();
}
}
.ComplementaryDay, .ComplementaryDay-fake {
@include make-col();
}
.ComplementaryDays-splitter {
width: 100%;
}
}
.Month, .ComplementaryDays {
margin-left: -$calendar-gutter;
margin-right: -$calendar-gutter;
}
.ComplementaryDay {
margin-top: $calendar-gutter;
}
.ComplementaryDay-fake {
padding: 0.5em;
}
.Day {
padding: 0.5em;
border: 1px solid black;
border-radius: $border-radius;
}
.DecadeName {
text-align: center;
font-weight: 600;
font-size: 1.2em;
}
.Day-name {
font-size: 2em;
font-weight: 600;
}
.Day-decade {
font-weight: 600;
}
.Day-today {
background: $gray-300;
}

View file

@ -30,7 +30,7 @@ type DateProps = MonthProps & {
}; };
function DecadeName({name}: { name: string }): JSX.Element { function DecadeName({name}: { name: string }): JSX.Element {
return <div className="DecadeName">{name}</div>; return <div className="WeekdayName">{name}</div>;
} }
function DayDetail({jdn}: { jdn: number }): JSX.Element { function DayDetail({jdn}: { jdn: number }): JSX.Element {
@ -44,9 +44,9 @@ function NormalDay({year, month, day, todayJDN}: DateProps & { todayJDN: number
const jdn = frJDN(year, month, day); const jdn = frJDN(year, month, day);
const rural = dateRuralName(month, day)!; const rural = dateRuralName(month, day)!;
const mobile = useMobileTooltipProps(); const mobile = useMobileTooltipProps();
return <div className={`Day NormalDay ${jdn === todayJDN ? 'Day-today' : ''}`}> return <div className={`Day ${jdn === todayJDN ? 'Day-today' : ''}`}>
<div className="Day-name">{day}</div> <div className="Day-name">{day}</div>
<div className="Day-decade">{decadeNames[(day - 1) % 10]}</div> <div className="Day-weekday">{decadeNames[(day - 1) % 10]}</div>
<div className="Day-rural"><abbr title={rural.title} {...mobile}>{rural.name}</abbr></div> <div className="Day-rural"><abbr title={rural.title} {...mobile}>{rural.name}</abbr></div>
<DayDetail jdn={jdn}/> <DayDetail jdn={jdn}/>
</div>; </div>;
@ -55,22 +55,18 @@ function NormalDay({year, month, day, todayJDN}: DateProps & { todayJDN: number
function NormalMonth({year, month, todayJDN}: MonthProps & { todayJDN: number }): JSX.Element { function NormalMonth({year, month, todayJDN}: MonthProps & { todayJDN: number }): JSX.Element {
const decadeHeads = decadeNames.map((name, i) => <DecadeName key={i} name={name}/>); const decadeHeads = decadeNames.map((name, i) => <DecadeName key={i} name={name}/>);
return <div className="Month"> return <div className="Month">
<div className="Month-decadeHead">{decadeHeads}</div> <div className="Month-weekdayHead">{decadeHeads}</div>
<div className="Month-decades">{ <div className="Month-days">{
Array.from(Array(3).keys()).map(i => <div key={i} className="Month-decade">{ Array.from(Array(30).keys()).map(i => <div key={i} className="DayOuter NormalDay">
Array.from(Array(10).keys()).map(j => <React.Fragment key={j}> <NormalDay year={year} month={month} day={i + 1 as FrenchDay} todayJDN={todayJDN}/>
<NormalDay year={year} month={month} day={i * 10 + j + 1 as FrenchDay} todayJDN={todayJDN}/> </div>)
{j % 2 === 1 && <div className="Month-decadeSplitter-small"/>}
{j === 4 && <div className="Month-decadeSplitter-medium"/>}
</React.Fragment>)
}</div>)
}</div> }</div>
</div>; </div>;
} }
function ComplementaryDay({year, month, day, todayJDN}: DateProps & { todayJDN: number }): JSX.Element { function ComplementaryDay({year, month, day, todayJDN}: DateProps & { todayJDN: number }): JSX.Element {
const jdn = frJDN(year, month, day); const jdn = frJDN(year, month, day);
return <div className={`Day ComplementaryDay ${jdn === todayJDN ? 'Day-today' : ''}`}> return <div className={`Day ${jdn === todayJDN ? 'Day-today' : ''}`}>
<div className="Day-name">{dateName(month, day)}</div> <div className="Day-name">{dateName(month, day)}</div>
<DayDetail jdn={jdn}/> <DayDetail jdn={jdn}/>
</div>; </div>;
@ -78,13 +74,13 @@ function ComplementaryDay({year, month, day, todayJDN}: DateProps & { todayJDN:
function ComplementaryDays({year, todayJDN}: { year: FrenchYear, todayJDN: number }): JSX.Element { function ComplementaryDays({year, todayJDN}: { year: FrenchYear, todayJDN: number }): JSX.Element {
const leap = frIsLeap(year); const leap = frIsLeap(year);
return <div className="ComplementaryDays">{ return <div className="Month">
Array.from(Array(6).keys()).map(i => <React.Fragment key={i}> <div className="Month-days">{
{(i < 5 || leap) && <ComplementaryDay year={year} month={13} day={i + 1 as FrenchDay} todayJDN={todayJDN}/>} Array.from(Array(leap ? 6 : 5).keys()).map(i => <div key={i} className="DayOuter ComplementaryDay">
{i === 5 && !leap && <div className="ComplementaryDay-fake"/>} <ComplementaryDay year={year} month={13} day={i + 1 as FrenchDay} todayJDN={todayJDN}/>
{i % 2 === 1 && <div className="ComplementaryDays-splitter"/>} </div>)
</React.Fragment>) }</div>
}</div>; </div>;
} }
export class Calendar extends MonthBasedCalendar<FrenchYear, FrenchMonth> { export class Calendar extends MonthBasedCalendar<FrenchYear, FrenchMonth> {

View file

@ -1,122 +1,7 @@
@import 'bootstrap/scss/functions'; @import 'bootstrap/scss/functions';
@import 'bootstrap/scss/variables'; @import 'bootstrap/scss/variables';
@import 'bootstrap/scss/mixins'; @import 'bootstrap/scss/mixins';
@import 'bootstrap/scss/forms';
@import 'bootstrap/scss/grid'; @import 'bootstrap/scss/grid';
@import 'bootstrap/scss/buttons';
@import '@common/ui/consts.scss'; @import '@common/ui/consts.scss';
@import '@common/ui/MonthBasedCalendar.scss'; @import '@common/ui/MonthBasedCalendar.scss';
@import '@common/ui/SevenDayWeek.scss';
.Calendar {
@include make-container();
}
.Month-weekdayHead {
display: none;
}
.Month-days {
@include make-row($gutter: 0);
> * {
@include make-col-ready();
}
}
.DayOuter {
padding: $calendar-gutter;
}
.DayFiller {
display: none;
}
.DayOuter {
display: flex;
@include make-col($size: 1, $columns: 2);
}
@include media-breakpoint-up(sm) {
.DayOuter, .WeekdayName {
@include make-col($size: 1, $columns: 3);
}
}
@include media-breakpoint-up(md) {
.DayOuter, .WeekdayName {
@include make-col($size: 1, $columns: 4);
}
}
@include media-breakpoint-up(lg) {
.DayOuter, .WeekdayName {
@include make-col($size: 1, $columns: 5);
}
}
@include media-breakpoint-up(xl) {
.Month-weekdayHead {
display: block;
@include make-row($gutter: 0);
position: sticky;
top: 0;
background: white;
margin-top: -$spacer * 7.5;
padding-top: $spacer * 7.5;
z-index: 19;
}
.Month-days {
margin-top: $spacer;
}
.DayOuter, .WeekdayName, .DayFiller {
@include make-col($size: 1, $columns: 7);
}
.Day-weekday {
display: none;
}
.DayFiller {
display: block;
}
}
.Month {
margin-left: -$calendar-gutter;
margin-right: -$calendar-gutter;
}
.Day, .DayFiller {
padding: 0.5em;
border-radius: $border-radius;
}
.Day {
flex: 1;
border: 1px solid black;
}
.DayFiller {
border: 1px solid transparent;
}
.WeekdayName {
text-align: center;
font-weight: 600;
font-size: 1.2em;
}
.Day-name {
font-size: 2em;
font-weight: 600;
}
.Day-weekday {
font-weight: 600;
}
.Day-today {
background: $gray-300;
}