最終的には以下のようにその週だけを表示したい

そのために編集を行う
ステップ1:PomodoroCalendar.vue
の <script>
の修正(データの準備と計算ロジックの変更)
現在の月の表示に必要なデータと、1週間分の表示に必要なデータを計算するロジックに変更します。
変更前 (PomodoroCalendar.vue
の <script>
の data
、computed
部分):
JavaScript
data() {
const today = new Date();
const currentYear = today.getFullYear();
const currentMonth = today.getMonth() + 1;
return {
year: currentYear,
month: currentMonth,
daysOfWeek: ["日", "月", "火", "水", "木", "金", "土"],
todayDate: today.getDate(),
todayMonth: currentMonth,
todayYear: currentYear,
calendarWorkLogs: [...this.workLogs],
};
},
computed: {
daysInMonth() {
return new Date(this.year, this.month, 0).getDate();
},
firstDayOfMonth() {
return new Date(this.year, this.month - 1, 1).getDay(); // 0:日, 1:月,...
},
calendarGrid() {
const grid = [];
let week = [];
let dayCounter = 1;
// 月の初めまでの空白を追加
for (let i = 0; i < this.firstDayOfMonth; i++) {
week.push(null);
}
while (dayCounter <= this.daysInMonth) {
week.push(new Date(this.year, this.month - 1, dayCounter));
if (week.length === 7) {
grid.push(week);
week = [];
}
dayCounter++;
}
// 月の終わりまでの空白を追加
while (week.length < 7 && week.length > 0) {
week.push(null);
}
if (week.length > 0) {
grid.push(week);
}
return grid;
},
},
変更後 (PomodoroCalendar.vue
の <script>
の data
、computed
部分):
JavaScript
data() {
const today = new Date();
const currentYear = today.getFullYear();
const currentMonth = today.getMonth() + 1;
const currentDay = today.getDate();
// 表示する週の開始日を計算 (例: 先週の月曜日)
const daysToMonday = today.getDay() === 0 ? 6 : today.getDay() - 1; // 今週の月曜日までの日数
const startOfWeek = new Date(today);
startOfWeek.setDate(currentDay - daysToMonday - 7); // 先週の月曜日
const weekDates = [];
for (let i = 0; i < 7; i++) {
const date = new Date(startOfWeek);
date.setDate(startOfWeek.getDate() + i);
weekDates.push(date);
}
return {
year: currentYear,
month: currentMonth,
daysOfWeek: ["日", "月", "火", "水", "木", "金", "土"],
todayDate: today.getDate(),
todayMonth: currentMonth,
todayYear: currentYear,
calendarWorkLogs: [...this.workLogs],
weekDates: weekDates, // 表示する1週間の日付配列
};
},
computed: {
calendarGrid() {
return [this.weekDates]; // 1週間分のデータだけを持つ配列を返す
},
},
変更点の解説:
data()
の変更:currentDay
: 今日の日付を取得します。startOfWeek
: 表示する週の開始日(ここでは先週の月曜日)を計算します。today.getDay()
: 今日の曜日(0:日, 1:月, ... 6:土)を取得します。daysToMonday
: 今週の月曜日までの日数を計算します。日曜日の場合は 6、月曜日の場合は 0、... 土曜日の場合は 5 になります。startOfWeek.setDate(currentDay - daysToMonday - 7)
: 今日の日付から今週の月曜日までの日数とさらに7日(先週)を引くことで、先週の月曜日のDate
オブジェクトを作成します。
weekDates
:startOfWeek
を基準に、7日分のDate
オブジェクトを格納した配列を作成します。これが表示する1週間の日付データとなります。year
とmonth
は今日のものを使用していますが、必要に応じてweekDates
の最初の日付から取得するように変更できます。calendarWorkLogs
: 変更なし。
computed.calendarGrid()
の変更:- 以前は月の全日を含む二次元配列を生成していましたが、変更後は
this.weekDates
を要素とする一次元配列をさらに配列で囲んだ[[...]]
の形式で返します。これは、テンプレートのv-for
が週ごとの行を処理することを前提としているため、1週間分のデータを1つの「週」として扱います。
- 以前は月の全日を含む二次元配列を生成していましたが、変更後は
ステップ2:PomodoroCalendar.vue
の <template>
の修正(表示の変更)
テンプレートの v-for
を weekDates
配列に合わせて修正します。
変更前 (PomodoroCalendar.vue
の <template>
部分):
HTML
<template>
<div>
<h2>{{ year }}年 {{ month }}月</h2>
<table>
<thead>
<tr>
<th v-for="day in daysOfWeek" :key="day">{{ day }}</th>
</tr>
</thead>
<tbody>
<tr v-for="(week, index) in calendarGrid" :key="index">
<td
v-for="(date, i) in week"
:key="i"
:class="{ today: isToday(date), empty: !date }"
>
{{ date ? date.getDate() : "" }}
<div v-if="date">
<div v-for="log in getWorkLogsForDate(date)" :key="log.startTime">
- {{ log.task }} ({{ log.startTime }} - {{ log.endTime }})
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</template>
変更後 (PomodoroCalendar.vue
の <template>
部分):
HTML
<template>
<div>
<h2>
{{ weekDates[0] ? weekDates[0].getFullYear() : "" }}年
{{ weekDates[0] ? weekDates[0].getMonth() + 1 : "" }}月
({{ formatDateRange }})
</h2>
<table>
<thead>
<tr>
<th v-for="day in daysOfWeek" :key="day">{{ day }}</th>
</tr>
</thead>
<tbody>
<tr>
<td
v-for="date in weekDates"
:key="date ? date.getTime() : i"
:class="{ today: isToday(date) }"
>
{{ date ? date.getDate() : "" }}
<div v-if="date">
<div v-for="log in getWorkLogsForDate(date)" :key="log.startTime">
- {{ log.task }} ({{ log.startTime }} - {{ log.endTime }})
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
// ... (script 部分はステップ1で変更)
export default {
// ... (name, props, data, watch)
computed: {
calendarGrid() {
return [this.weekDates];
},
formatDateRange() {
if (this.weekDates.length === 7 && this.weekDates[0] && this.weekDates[6]) {
const startDay = this.weekDates[0].getDate();
const endDay = this.weekDates[6].getDate();
return `${startDay} - ${endDay}日`;
}
return "";
},
},
methods: {
// ... (isToday, getWorkLogsForDate)
},
};
</script>
変更点の解説:
<h2>
部分の修正:- 表示する年と月を
weekDates
配列の最初の要素から取得するように変更しました。 - 表示する日付の範囲を示す
formatDateRange
computed プロパティを追加し、表示しています。
- 表示する年と月を
<tbody>
部分の修正:- 週ごとの
<tr>
のv-for
を削除し、直接weekDates
を<td>
でループするように変更しました。1週間分のデータがweekDates
に格納されているため、1行で表示できます。 <td>
のkey
をdate ? date.getTime() : i
に変更しました。Date
オブジェクトが存在する場合はそのタイムスタンプを、存在しない場合はインデックスを使用します(今回はweekDates
に常にDate
オブジェクトが入るので、主に TypeScript などでの型安全性を考慮した記述です)。.empty
クラスの条件を削除しました。weekDates
には常に日付が入るため、空のセルはなくなります。
- 週ごとの
ステップ3:PomodoroCalendar.vue
の <script>
の methods
の修正(日付の比較)
isToday
メソッドが Date
オブジェクトを受け取るように修正します。
変更前 (PomodoroCalendar.vue
の <script>
の methods
部分):
JavaScript
methods: {
isToday(date) {
return (
date &&
date.getDate() === this.todayDate &&
date.getMonth() + 1 === this.todayMonth &&
date.getFullYear() === this.todayYear
);
},
getWorkLogsForDate(date) {
if (!date) {
return [];
}
const formattedDate = `${date.getFullYear()}-${(date.getMonth() + 1)
.toString()
.padStart(2, "0")}-${date.getDate().toString().padStart(2, "0")}`;
return this.calendarWorkLogs.filter((log) => log.date === formattedDate);
},
// ...
},
変更後 (PomodoroCalendar.vue
の <script>
の methods
部分):
JavaScript
methods: {
isToday(date) {
if (!date) return false;
return (
date.getDate() === this.todayDate &&
date.getMonth() === this.todayMonth - 1 && // JavaScript の month は 0-indexed
date.getFullYear() === this.todayYear
);
},
getWorkLogsForDate(date) {
if (!date) {
return [];
}
const formattedDate = `${date.getFullYear()}-${(date.getMonth() + 1)
.toString()
.padStart(2, "0")}-${date.getDate().toString().padStart(2, "0")}`;
return this.calendarWorkLogs.filter((log) => log.date === formattedDate);
},
// ...
},
変更点の解説:
isToday(date)
の修正:- 引数
date
がDate
オブジェクトであることを前提として比較を行います。 date.getMonth()
は 0 から始まるため、this.todayMonth - 1
と比較するように修正しました。
- 引数

このような形になった
この状態だとタイマー終了後タスクが反映されなくなってしまったため
再度紐付けを行う
再度紐付け
問題点:
現在の App.vue
の handleWorkFinished
関数では、カレンダーが表示されている場合に calendarRef.value.addWorkLog(logData)
を呼び出していますが、PomodoroCalendar
コンポーネントがマウントされる前にタイマーが終了した場合、calendarRef.value
が null
になっている可能性があります。
また、mounted
フックでの watch
は、画面遷移後に初期表示用の calendarWorkLogs
を反映する意図がありますが、タイマー終了後に即座に反映するためには別の仕組みが必要です。
修正方針:
App.vue
でタイマー終了時に受け取ったログをcalendarWorkLogs
に保持し続ける。PomodoroCalendar
がマウントされた際に、calendarWorkLogs
に保持されているログを自身に追加する。- タイマー終了時にカレンダーが表示されていれば、即座に
PomodoroCalendar
のaddWorkLog
を呼び出す。
ステップ1:App.vue
の <script>
の修正
handleWorkFinished
関数と mounted
フックを修正します。
JavaScript
setup() {
const route = useRoute();
const calendarRef = ref(null); // PomodoroCalendar コンポーネントの参照
const calendarWorkLogs = ref([]); // 作業ログを保持
const handleWorkFinished = (logData) => {
console.log("App.vue で作業終了イベントを受け取りました:", logData);
calendarWorkLogs.value.push(logData); // 作業終了時にログを calendarWorkLogs に追加
if (route.path === "/calendar" && calendarRef.value) {
calendarRef.value.addWorkLog(logData); // カレンダーが表示されていれば直接追加
}
};
return { route, calendarRef, calendarWorkLogs, handleWorkFinished };
},
mounted() {
this.$watch(
() => this.$route.path,
(newPath) => {
if (newPath === "/calendar" && this.calendarRef) {
// カレンダー表示時に保持しているログをすべて追加
this.calendarWorkLogs.value.forEach(log => {
this.calendarRef.value.addWorkLog(log);
});
// 追加後にクリア (即時反映のため、保持は不要)
this.calendarWorkLogs.value = [];
}
}
);
},
};
変更点の解説:
setup()
関数の変更:calendarWorkLogs
のコメントを修正し、作業ログを保持する役割を明確にしました。
mounted()
フックの変更:- カレンダー画面 (
/calendar
) に遷移し、calendarRef
が存在する場合に、calendarWorkLogs
に保持されているすべてのログをcalendarRef.value.addWorkLog(log)
を使ってPomodoroCalendar
に追加します。 - ログを追加後、
calendarWorkLogs.value = [];
で配列をクリアします。これは、ログを即時反映するため、App.vue
で保持する必要がなくなるためです。
- カレンダー画面 (
ステップ2:PomodoroCalendar.vue
の <script>
の修正(マウント時のログ反映)
PomodoroCalendar
がマウントされた際に、props
で受け取った workLogs
を自身の calendarWorkLogs
に反映させる処理を追加します。
JavaScript
data() {
const today = new Date();
const currentYear = today.getFullYear();
const currentMonth = today.getMonth() + 1;
const currentDay = today.getDate();
const daysToMonday = today.getDay() === 0 ? 6 : today.getDay() - 1;
const startOfWeek = new Date(today);
startOfWeek.setDate(currentDay - daysToMonday - 7);
const weekDates = [];
for (let i = 0; i < 7; i++) {
const date = new Date(startOfWeek);
date.setDate(startOfWeek.getDate() + i);
weekDates.push(date);
}
const hours = Array.from({ length: 24 }, (_, i) => i);
return {
year: currentYear,
month: currentMonth,
daysOfWeek: ["日", "月", "火", "水", "木", "金", "土"],
todayDate: today.getDate(),
todayMonth: currentMonth,
todayYear: currentYear,
calendarWorkLogs: [], // 初期化を空にする
weekDates: weekDates,
hours: hours,
};
},
watch: {
workLogs(newWorkLogs) {
this.calendarWorkLogs = [...newWorkLogs];
},
},
mounted() {
// props で受け取った initialWorkLogs を初期表示時に追加
this.workLogs.forEach(log => {
this.addWorkLog(log);
});
},
methods: {
addWorkLog(logData) {
this.calendarWorkLogs.push(logData);
},
// ... (他のメソッドは変更なし)
},
変更点の解説:
data()
の変更:calendarWorkLogs
の初期化を[]
に変更しました。初期表示はmounted
フックで行います。
mounted()
フックの追加:- コンポーネントがマウントされた際に、
props
で受け取ったworkLogs
をforEach
でループ処理し、自身のaddWorkLog
メソッドを使ってcalendarWorkLogs
に追加します。これにより、初期表示時にApp.vue
から渡されたログが表示されます。
- コンポーネントがマウントされた際に、
これらの変更を加えることで、タイマー終了後にカレンダー画面に遷移していれば即座にタスクが反映され、カレンダー画面が既に表示されている場合でも、タイマー終了後にタスクが追加されるようになります。
マウントされるってどういう意味
- マウントされる: このコンポーネントの実体が、HTML の特定の場所(通常は
index.html
内のid="app"
の要素)に組み込まれ、ブラウザの画面に描画されることです。初めてユーザーの目に見えるようになり、データに基づいて表示が変化したり、ユーザーの操作に応じたりできるようになります。
これでもだめ