mirror of
https://github.com/quantum5/qcal.git
synced 2025-04-24 17:51:57 -04:00
Factor out common day wrapping logic and week handling
This commit is contained in:
parent
a8edb3cfab
commit
766a222979
|
@ -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;
|
||||||
|
}
|
||||||
|
|
50
common/src/ui/SevenDayWeek.scss
Normal file
50
common/src/ui/SevenDayWeek.scss
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue