Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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 package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"lodash.keyby": "^4.6.0",
"lodash.mapvalues": "^4.6.0",
"lodash.uniq": "^4.5.0",
"moment": "^2.22.2",
"popper.js": "^1.12.9",
"vue": "^2.5.3"
},
Expand Down
219 changes: 198 additions & 21 deletions src/App.vue
Original file line number Diff line number Diff line change
@@ -1,24 +1,109 @@
<template>
<div id="app">
<div id="app" class="bg-light">
<CornerBanner url="https://github.com/mkopinsky/howmanychagim"/>
<div class="top">
<h1>How many Chagim?</h1>
<h3 class="year-selector">
<a
v-for="year in availableYears"
:class="{'px-1': true, 'active': year===selectedYear}"
href="#"
@click="selectYear(year)"
>{{ year }}</a>
</h3>
<div class="grand-totals mb-3">
<h4>
Total: <span class="badge badge-warning">{{ totalWeekdays() }}</span> work days,
<span class="badge badge-secondary">{{ totalWeekends() }}</span> weekends
</h4>
</div>
<div class="col-lg-6 offset-lg-3">
<div class="card">
<h5 class="card-header d-none">
Settings
</h5>
<div class="card-body">
<div class="form-group row">
<label class="col-sm-5 col-form-label">Select a Year</label>
<div class="col-sm-7 btn-group-toggle btn-group" data-toggle="buttons">
<label v-for="year in availableYears" class="btn btn-outline-primary" :class="{active: year==selectedYear}">
<input type="radio" :value="year" v-model="selectedYear"/>
{{ year }}
</label>
</div>
</div>
<div class="form-group row">
<label class="col-sm-5 col-form-label">Choose your Work Week</label>
<div class="col-sm-7 btn-group-toggle btn-group" data-toggle="buttons">
<label v-for="day, i in weekdays" class="btn btn-outline-primary" @click="toggleDay(day)" :class="{active: settings.weekdays[day]}">
{{ day[0] }}
</label>
</div>
</div>

<div class="form-group row">
<label class="col-sm-5 col-form-label">What will you take off?</label>
<div class="col-sm-7">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="defaultCheck1" checked>
<label class="form-check-label" for="defaultCheck1">
Yom tov
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="defaultCheck2">
<label class="form-check-label" for="defaultCheck2">
Chol Hamoed
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="defaultCheck3">
<label class="form-check-label" for="defaultCheck3">
Purim
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="defaultCheck4" checked>
<label class="form-check-label" for="defaultCheck4">
Tisha B'av
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="defaultCheck5">
<label class="form-check-label" for="defaultCheck5">
Minor Fast Days
</label>
</div>

</div>
</div>

</div>
<div class="card-footer mb-0">
<h4>Total: <span class="badge badge-primary">{{ totalWeekdays() }}</span> work days</h4>
<ul>
<li v-for="holidays, month in selectedHolidaysByMonth" v-if="holidays.length > 0">
<span class="badge badge-primary">{{ totalWeekdays(month) }}</span>
{{ month }}:
<span v-for="holiday, i in holidays">
<span style="border-bottom: 1px dotted black" v-b-tooltip.hover :title="holiday.title">
{{ formatShort(holiday.date) }}
</span>
<span v-if="i < holidays.length - 1">, </span>
</span>

</li>
</ul>
</div>
</div>
</div>
<div class="row">
<div class="row d-none">
<div class="col-lg-3">
<h2>Select a year</h2>
<div class="btn-group-toggle btn-group" data-toggle="buttons">
<label v-for="year in availableYears" class="btn btn-outline-primary" :class="{active: year==selectedYear}">
<input type="radio" :value="year" v-model="selectedYear"/>
{{ year }}
</label>
</div>
</div>

</div>
<div class="row col-lg-9 offset-lg-2 text-center">
<calendar
:year="selectedYear"
:selectedDays="selected"
:getClassesForDate="getClassesForDate"
/>
</div>
<div class="row d-none">

<div class="col-lg-3 col-sm-6" v-for="holidays, month in holidays.holidaysByMonth">
<div class="card">
Expand All @@ -44,7 +129,7 @@
</div>
</div>
</div>
<div id="footer" class="text-center">
<div id="footer" class="text-center mt-4">
&copy; 2018 Michael Kopinsky. Licensed under MIT.
</div>
</div>
Expand All @@ -58,46 +143,105 @@ import _keyby from 'lodash.keyby';
import _mapValues from 'lodash.mapvalues';
import _uniq from 'lodash.uniq';
import isWeekend from 'date-fns/is_weekend';
import moment from 'moment';

import calendar from './calendar/index.vue';
import CornerBanner from './CornerBanner.vue';

export default {
name: 'app',
components: {CornerBanner},
data() {
const currentYear = new Date().getFullYear();
return {
availableYears: [currentYear - 1, currentYear, currentYear + 1, currentYear + 2],
selectedYear: currentYear,
weekdays: moment.weekdays(),
settings: {
weekdays: {
'Sunday': false,
'Monday': true,
'Tuesday': true,
'Wednesday': true,
'Thursday': true,
'Friday': true,
'Saturday': false,
}
},
holidays: {
all: [],
holidaysByMonth: {}
},
selected: {}
};
},
components: {
calendar,
CornerBanner,
},
mounted() {
this.reloadHolidays();
},
computed: {
selectedHolidaysByMonth() {
return _mapValues(
this.holidays.holidaysByMonth,
holidays => holidays.filter(holiday => this.selected[holiday.date])
);
},

},
methods: {
getClassesForDate(date, month) {
if (date.format('MMMM') != month) {
return 'gray';
}

const dateStr = date.format('YYYY-MM-DD');
let classes = [];
if (this.selected[dateStr]) {
classes.push('active');
}

if (isWeekend(dateStr)) {
classes.push('weekend');
}

let holidays = this.holidays.all.filter(holiday => holiday.date == dateStr);
holidays.forEach(holiday => {
if (!!holiday.yomtov) {
classes.push('yomtov');
} else {
classes.push('holiday');
}
});

return classes.join(' ');
},
reloadHolidays() {
getHolidays(this.selectedYear).then(holidays => {
this.holidays = holidays;
this.selected = _mapValues(
_keyby(this.holidays.all, 'date'),
// Default to selecting yomtov days
holiday => !!holiday.yomtov
holiday => !!holiday.yomtov // && !isWeekend(holiday.date)
);
});
},
format(date) {
return format(date, 'ddd MMM Do');
},
formatShort(date) {
return format(date, 'ddd Do');
},
selectYear(year) {
this.selectedYear = year;
this.reloadHolidays();
},
toggle(date, event) {
this.selected[date] = event.target.checked;
toggleDay(day) {
this.settings.weekdays[day] = !this.settings.weekdays[day];
},
toggle(date) {
this.selected[date] = !this.selected[date];
},
totalWeekdays(month) {
let holidays = month
Expand Down Expand Up @@ -128,12 +272,18 @@ export default {
</script>

<style lang="scss">
$primary: #3276b1;
$danger: #ff4136;

@import "../node_modules/bootstrap/scss/bootstrap";
@import "../node_modules/bootstrap-vue/dist/bootstrap-vue.css";

#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #2c3e50;
margin: 60px 30px 20px;
padding: 60px 30px 20px;

.top {
text-align: center;
Expand Down Expand Up @@ -161,6 +311,33 @@ export default {
span.total {
font-weight: bold;
}

.day-cell {

&.yomtov {
border: 1px solid $primary;

&.active:hover,
&.active {
background: $primary;
color: white;
}
}

&.weekend, &.gray {
opacity: 0.7;
}

&.holiday {
border: 1px solid $warning;

&.active:hover,
&.active {
background: $warning;
color: white;
}
}
}
}

h1, h2 {
Expand Down
Loading