こんにちは!みさんです。
かなりお久しぶりになりましたが、今回からゆるゆる家計簿システムを作っていきます。
使用する環境と言語
【フロントエンド】
・HTML+CSS+JavaScript
【バックエンド、その他環境】
・PHP
・MAMP
・MySQL
今回はMAMP環境、データはMySQLにphpMyAdminで作成していきます。
家計簿システムの大まかな仕様
最終的には自分だけで使うシステムになるので、今回は暫定の仕様だけを決めて開発していきます。
途中で「こんな機能もほしいな」となれば都度追加しますし、いらないと思った機能はスルーして開発していきます!
- 支出収入データを登録
- カテゴリー、支払い方法、使用カード分け登録
- 登録データやカテゴリー系の編集と削除
- 登録データのフィルター検索(月ごとやカテゴリーごとなど)
かなりざっくりですが、CRUD処理+αな感じで開発していきます!
静的コーディング
いきなりPHPを使いながら開発をすすめるのは、初心者の私には難しいのでまずはHTMLとCSSでコーディングをしていきます。
完成形はこちら↓
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="./css/destyle.css">
<link rel="stylesheet" href="./css/style.css">
<title>家計簿アプリ</title>
</head>
<body>
<header>
<h1>家計簿アプリ</h1>
</header>
<main>
<section class="inputarea">
<form name="accountInput" action="./create.php" method="POST">
<input type="hidden" name="input_time" id="input_time" value="<?php echo date("Y/m/d-H:i:s"); ?>">
<div class="inputarea__item date">
<p>日付</p>
<label for="date"><input type="date" name="date" id="date" value="2022/05/03" required></label>
</div>
<div class="inputarea__item title">
<p>タイトル</p>
<input type="text" name="title" id="title" maxlength="15" required>
</div>
<div class="inputarea__item amount">
<p>金額</p>
<input type="number" name="amount" id="amount" step="1" maxlength="7" required>
</div>
<div class="inputarea__item type">
<label for="spending">
<input id="spending" type="radio" name="type" value="0" onchange="onRadioChangeType();" checked>支出
</label>
<label for="income">
<input type="radio" name="type" id="income" value="1" onchange="onRadioChangeType();">収入
</label>
</div>
<div class="inputarea__item cat spending" id="spendingCategoryBox">
<p>支出カテゴリー</p>
<select name="spending_category" id="spendingCategory">
<option value="0">選択してください</option>
<option value="1">食費</option>
<option value="2">日用品費</option>
<option value="3">交通費</option>
</select>
<a class="addbutton addbutton--category" href="">編集</a>
</div>
<div class="inputarea__item cat income" id="incomeCategoryBox">
<p>収入カテゴリー</p>
<select name="income_category" id="incomeCategory">
<option value="0">選択してください</option>
<option value="1">給料</option>
<option value="2">お小遣い</option>
</select>
<a class="addbutton addbutton--category" href="">編集</a>
</div>
<div id="paymentMethodBox" class="inputarea__item payment-method">
<p>支払い方法</p>
<select name="payment_method" id="paymentMethod" onchange="onRadioChangeCredit();onRadioChangeQr()">
<option value="0">選択してください</option>
<option value="1">現金</option>
<option value="2" id="radioCredit">クレジットカード</option>
<option value="3" id="radioQr">QR決済</option>
<option value="4">交通系IC</option>
</select>
<a class="addbutton addbutton--paymentmethod" href="">編集</a>
</div>
<div class="inputarea__item credit-select" id="creditSelectBox">
<label for="noanswer"><input type="radio" name="credit" id="noanswer" value="0" checked>選択しない</label>
<label for="carda"><input type="radio" name="credit" id="carda" value="1">カードA</label>
<label for="cardb"><input type="radio" name="credit" id="cardb" value="2">カードB</label>
<label for="cardc"><input type="radio" name="credit" id="cardc" value="3">カードC</label>
<a class="addbutton addbutton--credit" href="">編集</a>
</div>
<div class="inputarea__item qr-select" id="qrSelectBox">
<label for="noanswer"><input type="radio" name="qr" id="noanswer" value="0" checked>選択しない</label>
<label for="qr1"><input type="radio" name="qr" id="qr1" value="1">QR1</label>
<label for="qr2"><input type="radio" name="qr" id="qr2" value="2">QR2</label>
<a class="addbutton addbutton--qr" href="">編集</a>
</div>
<div class="inputarea__item memo">
<textarea name="memo" id="" cols="30" rows="5" placeholder="入力収支の詳細"></textarea>
</div>
<div class="inputarea__item register">
<input type="submit" value="登録">
</div>
</form>
</section>
<section class="outputarea">
<h2>収支一覧</h2>
<div class="data-list">
<table class="table table-striped">
<tr>
<th>収支日</th>
<th>タイトル</th>
<th>収入</th>
<th>支出</th>
<th>支出詳細</th>
<th>操作</th>
</tr>
<tr class="record">
<td>2022-05-02</td>
<td>
タイトル
<span>(カテゴリー)</span>
</td>
<td></td>
<td>
¥1000
<span>(支払い方法)</span>
</td>
<td>カード名</td>
<td>
<a class='edit' href='./edit.php'>編集</a>
<a class='delete' href='./delete.php'>削除</a>
</td>
</tr>
<tr class="record">
<td>2022-05-03</td>
<td>
タイトル
<span>(カテゴリー)</span>
</td>
<td>¥5000</td>
<td></td>
<td></td>
<td>
<a class='edit' href='./edit.php'>編集</a>
<a class='delete' href='./delete.php'>削除</a>
</td>
</tr>
</table>
</div>
</section>
</main>
<footer>
</footer>
<script src="./script.js"></script>
</body>
</html>
ポイント
・<form>の直下にtype=”hidden”のinputタグを置き、フォームの入力日時を送信する
(出力時の並び替えのときに日にちのみだと順番がずれるため)
・labelのforとinputのidを項目ごと統一
・分かりやすいnameをつける
・カテゴリーや支払い方法など選択項目には各統一のnameをつける
・支出or収入欄のinput、支払い方法のselectにイベントを設置(JSでイベント登録)
※style.cssの前にリセットCSSを読み込んでいます。
header {
height: 5rem;
}
header h1 {
font-size: 2.4rem;
line-height: 5rem;
font-weight: bold;
padding-left: 1.6rem;
}
.inputarea {
margin: 2rem 3.2rem 0;
}
.inputarea .inputarea__item {
margin: 1.6rem 0;
}
.inputarea .inputarea__item.date, .inputarea .inputarea__item.title, .inputarea .inputarea__item.amount, .inputarea .inputarea__item.cat, .inputarea .inputarea__item.payment-method, .inputarea .inputarea__item.add-item {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
.inputarea .inputarea__item.date > p, .inputarea .inputarea__item.title > p, .inputarea .inputarea__item.amount > p, .inputarea .inputarea__item.cat > p, .inputarea .inputarea__item.payment-method > p, .inputarea .inputarea__item.add-item > p {
font-size: 1.6rem;
margin-right: 2rem;
}
.inputarea .inputarea__item.cat {
display: none;
}
.inputarea .inputarea__item.cat.show {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
}
.inputarea .inputarea__item.payment-method {
display: none;
}
.inputarea .inputarea__item.payment-method.show {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
}
.inputarea .inputarea__item.credit-select, .inputarea .inputarea__item.qr-select {
display: none;
}
.inputarea .inputarea__item.credit-select > p, .inputarea .inputarea__item.qr-select > p {
font-size: 1.6rem;
}
.inputarea .inputarea__item.credit-select.show, .inputarea .inputarea__item.qr-select.show {
display: block;
}
.inputarea .inputarea__item.add-item .add-item-name {
margin-right: 1rem;
}
.inputarea .inputarea__item label {
font-size: 1.6rem;
}
.inputarea .addbutton {
display: inline-block;
padding: .3rem;
margin-left: 1rem;
border: solid .1rem #000;
border-radius: .5rem;
background-color: #eee;
font-size: 1.2rem;
}
.outputarea {
margin: 2rem 3.2rem 0;
}
.outputarea h2 {
text-align: center;
font-size: 2.4rem;
}
.data-list {
margin-top: 2rem;
}
.data-list table {
border-collapse: collapse;
width: 100%;
margin-bottom: 1rem;
color: #212529;
vertical-align: top;
font-size: 1.4rem;
}
.data-list table tr {
border-bottom: solid .1rem #ddd;
}
.data-list table tr:first-of-type {
background-color: #ddd;
}
.data-list table tr th, .data-list table tr td {
padding: 1rem .3rem;
}
.data-list table tr th span, .data-list table tr td span {
font-size: 1rem;
}
.data-list table tr th a, .data-list table tr td a {
padding: .5rem 1rem;
border-radius: .5rem;
}
.data-list table tr th a.edit, .data-list table tr td a.edit {
color: #198754;
background-color: #b6f9d9;
margin-right: .5rem;
}
.data-list table tr th a.delete, .data-list table tr td a.delete {
color: #dc3545;
background-color: #ffc8c3;
}
.data-list.edit {
margin: 0 3.2rem;
}
.data-list.edit table {
width: 40%;
}
.data-list.edit table tr td:first-of-type,
.data-list.edit table tr th:first-of-type {
width: 65%;
}
.data-list.edit table tr td:last-of-type,
.data-list.edit table tr th:last-of-type {
width: 35%;
min-width: 13rem;
}
.back-link-box {
margin: 2rem 3.2rem;
}
.back-link-box a {
font-size: 1.6rem;
border-bottom: solid .1rem #000;
}
//クレジットカード選択要素取得
const creditSelectBox = document.getElementById("creditSelectBox");
//QR決済選択要素取得
const qrSelectBox = document.getElementById("qrSelectBox");
//支払い方法選択要素取得
const paymentMethod = document.getElementById("paymentMethod");
//支出カテゴリー要素取得
const spendingCategoryBox = document.getElementById("spendingCategoryBox");
//収入カテゴリー要素取得
const incomeCategoryBox = document.getElementById("incomeCategoryBox");
//支出収入ラジオボタン取得
const typeChecked = document.accountInput.type;
//支払い方法コンテンツ要素取得
const paymentMethodBox = document.getElementById("paymentMethodBox");
//支出収入切り替えのイベント
function onRadioChangeType(number) {
typeChecked[number].checked = true;
if (typeChecked[1].checked) { //収入が選択された時
paymentMethodBox.classList.remove("show");
spendingCategoryBox.classList.remove("show");
incomeCategoryBox.classList.add("show");
creditSelectBox.classList.remove("show");
qrSelectBox.classList.remove("show");
} else if (typeChecked[0].checked) { //支出が選択された特
paymentMethodBox.classList.add("show");
spendingCategoryBox.classList.add("show");
incomeCategoryBox.classList.remove("show");
if (paymentMethod.value === "2") {
creditSelectBox.classList.add("show");
} else if (paymentMethod.value === "3") {
qrSelectBox.classList.add("show");
}
}
}
//クレジットカード選択時のイベント
function onRadioChangeCredit() {
if (paymentMethod.value === "2"){
creditSelectBox.classList.add("show");
} else if(paymentMethod.value !== "2"){
creditSelectBox.classList.remove("show");
}
}
//QR決済選択時のイベント
function onRadioChangeQr() {
if (paymentMethod.value === "3"){
qrSelectBox.classList.add("show");
} else if(paymentMethod.value !== "3") {
qrSelectBox.classList.remove("show");
}
}
収入を選択すると支払い方法の要素が表示されなくなったり、クレジットカードやQR決済を選択時は種類を選択する要素が表示されたりする動きをJavaScriptで作っています。
私の今後の復習のために、JavaScriptのプログラムを以下で解説します。
JavsScript解説
//クレジットカード選択要素取得
const creditSelectBox = document.getElementById("creditSelectBox");
//QR決済選択要素取得
const qrSelectBox = document.getElementById("qrSelectBox");
//支払い方法選択要素取得
const paymentMethod = document.getElementById("paymentMethod");
//支出カテゴリー要素取得
const spendingCategoryBox = document.getElementById("spendingCategoryBox");
//収入カテゴリー要素取得
const incomeCategoryBox = document.getElementById("incomeCategoryBox");
//支出収入ラジオボタン取得
const typeChecked = document.accountInput.type;
//支払い方法コンテンツ要素取得
const paymentMethodBox = document.getElementById("paymentMethodBox");
以上は複数の関数で使用するので、インポート用ファイルを作成し定義しています。
2〜10行目、14行目の要素取得プログラムではあらかじめid指定しておいた要素を「.getElementById」で変数に格納しています。
12行目のプログラムは、支出or収入のラジオボタンを取得し、変数に格納しています。
それでは次のプログラムです。
//支出収入切り替えのイベント
function onRadioChangeType(number) {
typeChecked[number].checked = true;
if (typeChecked[1].checked) { //収入が選択された時
paymentMethodBox.classList.remove("show");
spendingCategoryBox.classList.remove("show");
incomeCategoryBox.classList.add("show");
creditSelectBox.classList.remove("show");
qrSelectBox.classList.remove("show");
} else if (typeChecked[0].checked) { //支出が選択された特
paymentMethodBox.classList.add("show");
spendingCategoryBox.classList.add("show");
incomeCategoryBox.classList.remove("show");
if (paymentMethod.value === "2") {
creditSelectBox.classList.add("show");
} else if (paymentMethod.value === "3") {
qrSelectBox.classList.add("show");
}
}
}
選択されている項目によって、関連要素のクラスを操作して表示←→非表示を切り替えるようにするプログラムです。ただコメントだけではわかりにくいので、フローチャート的なものも載せておきます↓

収入を選択している時は、支払い方法を非表示にする処理だけでOK!としてしまうと、以下のように支払い方法の選択部分は非表示になりますが、クレジットやQR決済の選択要素が残ってしまいます。
それでは次のプログラムです。
//クレジットカード選択時のイベント
function onRadioChangeCredit() {
if (paymentMethod.value === "2"){
creditSelectBox.classList.add("show");
} else if(paymentMethod.value !== "2"){
creditSelectBox.classList.remove("show");
}
}
//QR決済選択時のイベント
function onRadioChangeQr() {
if (paymentMethod.value === "3"){
qrSelectBox.classList.add("show");
} else if(paymentMethod.value !== "3") {
qrSelectBox.classList.remove("show");
}
}
この2つの関数はほとんど中身は同じです。支払い方法でクレジットカードやQR決済が選択されたときに、どのカード or QR決済なのかを選択する要素に”show”クラスの追加←→削除を切り替えて、表示非表示にする処理を書いています。
以上が全てのJavaScriptのプログラムです。
最後に
ここまでの静的コーディングが終えると、支出収入の切り替えや、支払い方法によって更に選択項目が現れるなどの動きが出るようになります。
次回はデータベースを用意して入力内容が実際にデータベースに登録されるように実装していきます。
最後までお読みいただきありがとうございました。
コメント