Skip to content

Commit 6270505

Browse files
Merge branch 'development' of github.com:kota-yata/StudyAtHome into development
2 parents 51552ed + 808ce00 commit 6270505

File tree

6 files changed

+884
-6
lines changed

6 files changed

+884
-6
lines changed

jest.config.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
module.exports = {
22
roots: ['<rootDir>/src'],
3+
// setupFiles: ['<rootDir>/test/jest.setup.ts'],
4+
moduleNameMapper: {
5+
'^@/(.*)$': '<rootDir>/$1',
6+
'^~/(.*)$': '<rootDir>/$1'
7+
},
38
transform: {
49
'.*\\.(vue)$': 'vue-jest',
510
'^.+\\.tsx?$': 'ts-jest'

src/components/CalendarBar.vue

Lines changed: 322 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,322 @@
1+
<template>
2+
<v-container fill-height class="calendar-bar">
3+
<v-row align="center" class="pa-0 ma-0">
4+
<v-col cols="1" class="pa-0 ma-1">
5+
<v-card class="calendar-bar-ym" flat="true">
6+
<v-card-title class="calendar-bar-ym-title">
7+
{{ currentMonthString }}
8+
</v-card-title>
9+
<v-card-subtitle class="calendar-bar-ym-subtitle">
10+
{{ currentYearString }}
11+
</v-card-subtitle>
12+
</v-card>
13+
</v-col>
14+
<v-col
15+
v-for="date in dateListWindow.list"
16+
:key="date"
17+
v-touch="{
18+
left: () => dateListWindow.nextList(),
19+
right: () => dateListWindow.prevList()
20+
}"
21+
cols="0"
22+
class="pa-0 ma-0"
23+
>
24+
<v-card
25+
class="calendar-bar-date elevation-4"
26+
flat="false"
27+
:class="{
28+
current: fmtft(date) === fmtft(dateListWindow.currentDate)
29+
}"
30+
@click="dateListWindow.selectDate(date)"
31+
>
32+
<v-card-title class="calendar-bar-date-title">
33+
{{ fmteeeee(date) }}
34+
</v-card-title>
35+
<v-card-subtitle class="calendar-bar-date-subtitle">
36+
{{ fmtd(date) }}
37+
</v-card-subtitle>
38+
</v-card>
39+
</v-col>
40+
</v-row>
41+
</v-container>
42+
</template>
43+
44+
<script lang="ts">
45+
import { Vue, Component, Prop, Emit, Watch } from 'vue-property-decorator'
46+
import add from 'date-fns/add'
47+
import format from 'date-fns/format'
48+
import formatISO from 'date-fns/formatISO'
49+
import isValid from 'date-fns/isValid'
50+
import ja from 'date-fns/locale/ja'
51+
52+
export type View = 'Day' | 'Weekday' | 'Week'
53+
export type StartWeekOn =
54+
| 'Sunday'
55+
| 'Monday'
56+
| 'Tuesday'
57+
| 'Wednesday'
58+
| 'Thursday'
59+
| 'Friday'
60+
| 'Saturday'
61+
export type CalendarBarConfig = {
62+
view: View
63+
startWeekOn: StartWeekOn
64+
}
65+
66+
export interface DateListWindow {
67+
list: Array<Date>
68+
currentDate: Date
69+
selectDate(date: Date): DateListWindow
70+
nextDay(): DateListWindow
71+
prevDay(): DateListWindow
72+
nextWeek(): DateListWindow
73+
prevWeek(): DateListWindow
74+
nextList(): DateListWindow
75+
prevList(): DateListWindow
76+
}
77+
78+
class DateListWindowImpl implements DateListWindow {
79+
view: View
80+
startWeekOn: StartWeekOn
81+
currentDate: Date
82+
list: Array<Date>
83+
84+
constructor(
85+
view: View = 'Week',
86+
startWeekOn: StartWeekOn = 'Monday',
87+
date: Date = new Date()
88+
) {
89+
this.view = view
90+
this.startWeekOn = view === 'Weekday' ? 'Monday' : startWeekOn
91+
this.currentDate = this.calcCurrentDate(
92+
view,
93+
isValid(date) ? date : new Date()
94+
)
95+
this.list = this.generateDateList(
96+
this.view,
97+
this.startWeekOn,
98+
this.currentDate
99+
)
100+
}
101+
102+
nextDay(): DateListWindow {
103+
if (this.view === 'Weekday' && this.currentDate.getDay() === 6) {
104+
return this.addDays(2)
105+
} else {
106+
return this.addDays(1)
107+
}
108+
}
109+
110+
prevDay(): DateListWindow {
111+
if (this.view === 'Weekday' && this.currentDate.getDay() === 1) {
112+
return this.addDays(-2)
113+
} else {
114+
return this.addDays(-1)
115+
}
116+
}
117+
118+
nextWeek = (): DateListWindow => this.addDays(7)
119+
prevWeek = (): DateListWindow => this.addDays(-7)
120+
nextList = (): DateListWindow =>
121+
this.view === 'Day' ? this.nextDay() : this.nextWeek()
122+
123+
prevList = (): DateListWindow =>
124+
this.view === 'Day' ? this.prevDay() : this.prevWeek()
125+
126+
selectDate(date: Date): DateListWindow {
127+
this.currentDate = this.calcCurrentDate(
128+
this.view,
129+
isValid(date) ? date : new Date()
130+
)
131+
this.list = this.generateDateList()
132+
return this
133+
}
134+
135+
private calcCurrentDate(view: View, date: Date): Date {
136+
let currentDate: Date = date
137+
if (view === 'Weekday' && date.getDay() === 0) {
138+
currentDate = add(date, { days: 1 })
139+
}
140+
return currentDate
141+
}
142+
143+
private addDays(value: number): DateListWindow {
144+
return this.selectDate(add(this.currentDate, { days: value }))
145+
}
146+
147+
private firstDateOfList: (
148+
view: View,
149+
startWeekOn: StartWeekOn,
150+
date: Date
151+
) => Date = function(view: View, startWeekOn: StartWeekOn, date: Date) {
152+
const dowList: Array<StartWeekOn> = [
153+
'Sunday',
154+
'Monday',
155+
'Tuesday',
156+
'Wednesday',
157+
'Thursday',
158+
'Friday',
159+
'Saturday'
160+
]
161+
let firstDate: Date = date
162+
switch (view) {
163+
case 'Day': {
164+
firstDate = date
165+
break
166+
}
167+
default: {
168+
const idx = dowList.indexOf(startWeekOn)
169+
const startDay: number = idx >= 0 ? idx : 1
170+
firstDate = add(date, { days: (startDay - (7 + date.getDay())) % 7 })
171+
break
172+
}
173+
}
174+
return firstDate
175+
}
176+
177+
private sizeOfList(view: View): number {
178+
return view === 'Week' ? 7 : view === 'Weekday' ? 6 : 1
179+
}
180+
181+
private generateDateList(
182+
view: View = this.view,
183+
startWeekOn: StartWeekOn = this.startWeekOn,
184+
date: Date = this.currentDate
185+
): Array<Date> {
186+
const firstDate = this.firstDateOfList(view, startWeekOn, date)
187+
const size: number = this.sizeOfList(view)
188+
const list = Array<Date>(size)
189+
for (let i = 0; i < list.length; i++) {
190+
list[i] = add(firstDate, { days: i })
191+
}
192+
return list
193+
}
194+
}
195+
196+
@Component
197+
export default class CalendarBar extends Vue {
198+
@Prop({ default: new Date() }) date: Date | undefined
199+
@Prop({ default: { view: 'Week', startWeekOn: 'Monday' } }) config:
200+
| CalendarBarConfig
201+
| undefined
202+
203+
dateListWindow: DateListWindow = new DateListWindowImpl(
204+
this.config?.view ?? 'Week',
205+
this.config?.startWeekOn ?? 'Monday',
206+
this.date ?? new Date()
207+
)
208+
209+
@Emit('changeCurrentDate')
210+
changeCurrentDate(): Date {
211+
return this.dateListWindow.currentDate
212+
}
213+
214+
@Watch('dateListWindow.currentDate', { immediate: true })
215+
// @Watch('dateListWindow.currentDate')
216+
onChangeCurrentDate() {
217+
this.changeCurrentDate()
218+
}
219+
220+
get currentMonthString(): string {
221+
return format(this.dateListWindow.currentDate, 'M') + ''
222+
}
223+
224+
get currentYearString(): string {
225+
return format(this.dateListWindow.currentDate, 'yyyy')
226+
}
227+
228+
fmtd(date: Date): String {
229+
return format(date, 'd')
230+
}
231+
232+
fmteeeee(date: Date): String {
233+
return format(date, 'EEEEE', { locale: ja })
234+
}
235+
236+
fmtft(date: Date): String {
237+
return format(date, 'yyyy-MM-dd HH:mm:ss EEE')
238+
}
239+
240+
fmtISO(date: Date): String {
241+
return formatISO(date)
242+
}
243+
}
244+
</script>
245+
246+
<style lang="scss" scoped>
247+
.calendar-bar {
248+
color: $color-white;
249+
font-size: small;
250+
background: linear-gradient(
251+
to bottom,
252+
$color-white 0%,
253+
$color-white 50%,
254+
$color-base-color-01 50%,
255+
$color-base-color-01 100%
256+
);
257+
padding: 0 3px;
258+
}
259+
260+
.calendar-bar-ym {
261+
display: flex;
262+
flex-direction: column;
263+
align-items: center;
264+
justify-content: center;
265+
background: rgba(0, 0, 0, 0);
266+
height: 68px;
267+
min-width: 12px;
268+
font-family: 'Noto Sans JP', sans-serif;
269+
270+
.title {
271+
color: $color-base-color-01;
272+
font-size: 12px;
273+
}
274+
275+
.subtitle {
276+
color: $color-white;
277+
font-size: 10px;
278+
}
279+
}
280+
281+
.calendar-bar-ym-title {
282+
color: $color-base-color-01;
283+
font-size: 12px;
284+
padding: 8px 0 0 0;
285+
}
286+
287+
.calendar-bar-ym-subtitle {
288+
color: $color-white !important;
289+
font-size: 10px;
290+
padding: 8px 2px 16px;
291+
}
292+
293+
.calendar-bar-date {
294+
display: flex;
295+
flex-direction: column;
296+
background: $color-white;
297+
height: 68px;
298+
min-width: 16px;
299+
border-radius: 30px !important;
300+
align-items: center;
301+
justify-content: center;
302+
color: $color-gray;
303+
font-family: 'Noto Sans JP', sans-serif;
304+
margin: 0 3px;
305+
}
306+
307+
.calendar-bar-date.current {
308+
background: $color-yellow;
309+
}
310+
311+
.calendar-bar-date-title {
312+
color: $color-gray;
313+
font-size: 8px;
314+
padding: 8px 0 0 0;
315+
}
316+
317+
.calendar-bar-date-subtitle {
318+
color: $color-gray !important;
319+
font-size: 22px;
320+
padding: 8px 2px 16px;
321+
}
322+
</style>

0 commit comments

Comments
 (0)