main.html

<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8">
  <title>スケジュール管理アプリ</title>
  <link rel="stylesheet" href="style.css">
</head>

<body>
  <div class="calendar">
    <div>
      <button id="prev-btn">&lt;</button>
      <span id="current-month"></span>
      <button id="next-btn">&gt;</button>
    </div>
    <table id="calendar-table"></table>

    <div id="inputScreen">
      <button id="add-new-btn">メモの追加</button><br>
      <div id="addNewMemo">
        <input type="text" id="category" placeholder="Category"><br>
        <textarea id="memo" placeholder="Memo"></textarea>
        <button id="save-new-btn">メモの保存</button>
      </div>
      <div id="editMemo">
        <div id = "memo-editor"></div>
        <button id="save-edited-btn">メモの保存</button>
      </div>
    </div>
    <div id="memo-table"></div>
  </div>

  <script src="app.js"></script>
</body>

</html>

style.css

.calendar {
    width: 300px;
    text-align: center;
    font-family: Arial, sans-serif;
}
.calendar th {
    background-color: #f2f2f2;
    padding: 5px;
}
.calendar td {
    padding: 5px;
}
.calendar .current-month {
    font-weight: bold;
}

app.js

/* この配列にデータベースから取得したデータを入れる */
const MemoData = [['a', 1688716115, 'カテゴリ', 'テストだ'],
['b', 1688716115, 'カテゴリ', 'テストかも'],
['C', 1688802515, 'カテゴリ', 'テストだった'],];

// <https://tool.konisimple.net/date/unixtime?q=2023-07-07%2016:48:35>

/* カレンダー表示用の関数 */
function displayCalendar(year, month) {
    const calendarTable = document.getElementById("calendar-table");
    calendarTable.innerHTML = "";  // カレンダーテーブルをクリア

    const daysInMonth = new Date(year, month, 0).getDate(); // 指定した月の最終日を取得
    const firstDayOfWeek = new Date(year, month - 1, 1).getDay();  // 指定した月の初日の曜日を取得

    const currentMonthElement = document.getElementById("current-month");
    currentMonthElement.textContent = `${year}年${month}月`;

    /* 曜日のセルを作成 */
    const weekDayRow = document.createElement("tr");
    calendarTable.appendChild(weekDayRow);

    const weekDays = ["日", "月", "火", "水", "木", "金", "土"];
    for (let i = 0; i < 7; i++) {
        const weekDayCell = document.createElement("th");
        weekDayCell.textContent = weekDays[i];
        weekDayRow.appendChild(weekDayCell);
    }

    /* 日付のセルを作成 */
    let date = 1;
    for (let i = 0; i < 6; i++) {
        const weekRow = document.createElement("tr");
        calendarTable.appendChild(weekRow);

        for (let j = 0; j < 7; j++) {
            if ((i === 0 && j < firstDayOfWeek) || date > daysInMonth) {
                // 月の始まりより前か、月の終わりを超えた場合は空セルを作成
                const emptyCell = document.createElement("td");
                weekRow.appendChild(emptyCell);
            } else {
                /* 日付のセルを作成し、クリックイベントを追加 */
                const dateCell = document.createElement("td");
                dateCell.textContent = date;

                // 日付セルに四角形の枠を追加
                dateCell.style.border = "3px solid #ccc";
                dateCell.style.borderRadius = "10px";
                dateCell.style.padding = "10px";

                dateCell.addEventListener("click", function () {

                    /* ここから日付セルをクリックしたときの処理 */
                    const clickedDate = dateCell.textContent;
                    const clickedMonth = month;
                    const clickedYear = year;

                    displayMemo(clickedYear, clickedMonth, clickedDate, MemoData);     // メモ画面への遷移

                });

                weekRow.appendChild(dateCell);
                date++;
            }
        }
    }
}

/* メモ表示用の関数 */
function displayMemo(year, month, date, memoData) {
    const memoTable = document.getElementById("memo-table");
    memoTable.innerHTML = "";  // メモテーブルをクリア

    document.getElementById("inputScreen").style.display = "block";

    const addButton = document.getElementById("add-new-btn");
    addButton.addEventListener("click", function () {
        document.getElementById("editMemo").style.display = "none";
        document.getElementById("addNewMemo").style.display = "block";
        var targetTimestamp = convertToTimestamp(year, month, date);
        memoAdd(targetTimestamp);
    });

    /* 該当する日付の内容を新たに配列に */
    let n = 0;
    var chooseMemoData = [];

    for (let i = 0; i < memoData.length; i++) {
        var readMemoData = new Date(memoData[i][1] * 1000);

        var readYear = readMemoData.getFullYear();
        var readMonth = readMemoData.getMonth() + 1;
        var readDay = readMemoData.getDate();

        if (readYear == year && readMonth == month && readDay == date) {
            chooseMemoData[n] = memoData[i];
            n++;
        }
    }
    /* 配列chooseMemoDataに要素が入っているかどうかで、条件分岐 */
    if (chooseMemoData.length != 0) {
        /* テーブルを作成して表示 */
        // ヘッダセルの作成 
        const headerRow = document.createElement('tr');
        memoTable.appendChild(headerRow);

        const headerColumns = ['カテゴリ', 'メモ'];
        for (let i = 0; i < headerColumns.length; i++) {
            const th = document.createElement("th");
            th.textContent = headerColumns[i];
            headerRow.appendChild(th);
        }
        // テーブルボディの作成
        chooseMemoData.forEach((row) => {
            const tableRow = document.createElement('tr');
            const categoryCell = document.createElement('td');
            const memoCell = document.createElement('td');

            categoryCell.textContent = row[2];
            memoCell.textContent = row[3];

            categoryCell.addEventListener('click', () => {
                document.getElementById("addNewMemo").style.display = "none";
                document.getElementById("editMemo").style.display = "block";
                memoEdit(convertToTimestamp(year, month, date), row[2], row[3]);
            });

            memoCell.addEventListener('click', () => {
                document.getElementById("addNewMemo").style.display = "none";
                document.getElementById("editMemo").style.display = "block";
                memoEdit(convertToTimestamp(year, month, date), row[2], row[3]);
            });

            categoryCell.style.cursor = 'pointer';
            memoCell.style.cursor = 'pointer';

            tableRow.appendChild(categoryCell);
            tableRow.appendChild(memoCell);
            memoTable.appendChild(tableRow);
        });
    } else {
        alert('予定は追加されていません');
        document.getElementById("inputScreen").style.display = "none";
        document.getElementById("editMemo").style.display = "none";
        document.getElementById("addNewMemo").style.display = "none";
    }

    /* カレンダーを再表示 */
    displayCalendar(year, month);
}

/* TIMESTAMPに変更 */
function convertToTimestamp(year, month, date) {
    // Create a new Date object using the received values
    var dateObj = new Date(year, month - 1, date); // Note: Month is zero-based in JavaScript, so subtract 1

    // Get the timestamp in milliseconds
    var timestamp = dateObj.getTime();

    // If you want the timestamp in seconds, divide it by 1000
    // var timestampInSeconds = Math.floor(timestamp / 1000);

    return timestamp;
}

/* 新規メモ作成画面を表示する関数 */
function memoAdd(targetTimestamp) {
    const category = document.getElementById("category").value = "";
    const memo = document.getElementById("memo").value = "";
}

/* 既存メモを編集する関数 */
function memoEdit(timestamp, category, memo) {
    document.getElementById("category").textContent = category
    document.getElementById("memo").textContent = memo;

    const editorHTML = `
    <div>
      <input type="text" id="category" value="${category}">
    </div>
    <div>
      <textarea id="memo">${memo}</textarea>
    </div>
  `;

    const editorContainer = document.getElementById("memo-editor");
    editorContainer.innerHTML = editorHTML;
}

/* データ送信用の関数 */
function memodataSend() {
    var user = $('#id_user').val();

    var userData = {
        'user': user,           // UserID INT
        'daytime': daytime,     // DayTime TIMESTAMP
        'caetgory': category,   // Category TEXT
        'mamo': memo,           // Memo TEXT
        'csrfmiddlewaretoken': $('input[name=csrfmiddlewaretoken]').val()
    };
    // 単体テスト
    MemoData.push(userData);
    // sendData("/time_record", userData);
}

/* mainの処理 */
document.getElementById("inputScreen").style.display = "none";
document.getElementById("addNewMemo").style.display = "none";
document.getElementById("editMemo").style.display = "none";

// 現在の日付を取得
const today = new Date();
let currentYear = today.getFullYear();
let currentMonth = today.getMonth() + 1;

// カレンダー表示
displayCalendar(currentYear, currentMonth);

// 前の月に遷移するボタンのクリックイベント
const prevButton = document.getElementById("prev-btn");
prevButton.addEventListener("click", function () {
    currentMonth--;
    if (currentMonth === 0) {
        currentYear--;
        currentMonth = 12;
    }
    displayCalendar(currentYear, currentMonth);
});

// 次の月に遷移するボタンのクリックイベント
const nextButton = document.getElementById("next-btn");
nextButton.addEventListener("click", function () {
    currentMonth++;
    if (currentMonth === 13) {
        currentYear++;
        currentMonth = 1;
    }
    displayCalendar(currentYear, currentMonth);
});

const saveNewButton = document.getElementById("save-new-btn");
saveNewButton.sddEventListener("click", function () {
    var userData = [`AAA`, targetTimestamp, category, memo]
    MemoData.push(userData);
    document.getElementById("addNewMemo").style.display = "none";
});

const saveEditedButton = document.getElementById("save-edited-btn");
saveEditedButton.sddEventListener("click", function () {
    var userData = [`AAA`, timestamp, category, memo]
    alert(category);
    MemoData.push(userData);
    document.getElementById("editMemo").style.display = "none";
});