[react calendar] カレンダーを使って予約機能を作ろう_3
今回の時間では、予約された時間を照会し、その時間のボタンを無効にする機能と会員情報を保存する機能について説明します。
参考までに、予約に必要な情報は次のとおりです。(データベース)
必須入力が必要なデータは、医師番号、会員番号、診療科番号、予約年、月、日、予約時間です。
予約番号は自動的に数字が保存されるように設定されており、症状は必須入力ではありません。
また、予約状態は予約をするとYにデフォルト値が設定されている状態です。
受付日も現在の日付にデフォルト値が設定されています。
CREATE TABLE MEDICAL_SCHEDULE(
SCH_NUM INT PRIMARY KEY AUTO_INCREMENT -- 予約番号(PK)
,DOC_NUM VARCHAR(20) REFERENCES medical_doctor(DOC_NUM) ON DELETE CASCADE
,MEM_NUM VARCHAR(20) REFERENCES medical_member(MEM_NUM) ON DELETE CASCADE
,DEPT_NUM INT REFERENCES medical_dept(DEPT_NUM) ON DELETE CASCADE
,REG_DATE DATETIME DEFAULT CURRENT_TIMESTAMP
,SCH_DATE DATE NOT NULL -- 予約年、月、日
,SCH_TIME TIME NOT NULL -- 予約時間
,DETAIL VARCHAR(100) -- 症状
,SCH_STATUS VARCHAR(10) DEFAULT('Y') -- 予約状態
);
予約された時間を照会するquery
DBはmariaDBを使用しています!そのqueryはmybatisに適用されました。
<!-- 予約の有無を確認する(診療科と日付を選択したとき) -->
<select id="checkSchtime" resultMap="schedule">
SELECT SCH_TIME
FROM medical_schedule
WHERE DEPT_NUM = #{deptNum}
AND SCH_DATE = #{schDate}
</select>
上記queryで時間のボタンを無効化する
時間はListとして入力し、そのListをreturn文の中でmapを使ってボタンに適用しました。
まず、次のコードは時間の配列とボタンのdisabledをfalseのデフォルト値に設定しました。
そして、予約された時間があればfalseをtrueに変更し、クリックできないように防ぎました。
// timedata
const schTimes = ['09:00', '10:00', '11:00', '14:00', '15:00', '16:00', '17:00']
// 最初はschTimesにfalseを与える
const [chkAppoTime, setChkAppoTime] = useState(new Array(schTimes.length).fill(false))
//予約の有無を確認する(予約された時間がある場合はボタンを無効化)
useEffect(()=>{
axios.post('schedule/checkSchTime',appo)
.then((res)=>{
console.log(res.data)
// 予約がある時間帯を選別する
const availableTimes = res.data.map(time => {
// 秒を除いて分単位だけを残す
const [hours,minutes] = time.schTime.split(':')
return `${hours}:${minutes}`})
//schTimesと比較して、予約可能な時間が含まれているか確認します。
// 含まれていればtrue、含まれていなければfalse
const updatedChkAppoTime = schTimes.map(time => availableTimes.includes(time));
// console.log(`updateTime: ` + updatedChkAppoTime)
//チェックが終わったら chkAppoTimeを更新
setChkAppoTime(updatedChkAppoTime)
})
.catch((error)=>{
console.log(error)
})
},[appo])
次のコードは、リターン文の中でユーザーが時間ボタンを見ることができるように実装されたコードです。
<div className='sch-time'>
<div className='sch-btn'>
{schTimes.map((time,i) => (
<button
key={time}
type='button' className='sch-button'
disabled={chkAppoTime[i]}
value={time}
onClick={clickTime}>
{time}</button>))
}
</div>
<div className='sch-status'> 🟦選択中 ⬜予約不可</div>
</div>
診療科と日付を選択すると、次のように予約がある時間帯はボタンをクリックできなくなります。
時間の選択と情報の保存
カレンダーで日付を指定すると、appoの情報も変更されるように設定し、リアルタイムで日付のデータを受け取れるようにしました。
その後、患者が時間を選択すると、選択した時間も保存されるように設定しました。
選択したボタンの効果は、クリックしても太字の値が変わらないように指定したものです。
// schDateを選択すると appo情報も変わるように設定(リアルタイムで schDate更新)
useEffect(() => {
setAppo(prevAppo => ({
...prevAppo,
schDate: moment(value).format("YYYY-MM-DD")
}));
}, [value])
// 予約時間 input
const timeInput = useRef();
// 患者が選択した時間
const choseData = useRef()
// 予約時間を選択
function clickTime(e){
//選択したボタンの太文字効果を保つ
var btns = document.querySelectorAll('.sch-button');
btns.forEach(function (btn, i) {
if (e.currentTarget == btn) {
btn.classList.add("active");
} else {
btn.classList.remove("active");
}
});
// 選択した時間を保存
setAppo({...appo,
[timeInput.current.name] : e.target.value
})
}
会員情報データの保存
上記のコードまでで、医師番号、診療科番号、予約日(年・月・日・時間)までの情報を保存できるようになりました。最後に会員の番号が必要だが、ログインするとsessionStorageに会員の番号と名前が保存されるように事前に設定してあるので、sessionStorageにあるデータを呼び出すだけでよいです。(ログインに関する機能説明は投稿していない....いつかは..できることを願って)sessionStorageは文字列として値が保存されているため、JSONパースでその文字列をオブジェクトに変換する必要があります。
const loginInfo = JSON.parse(window.sessionStorage.getItem('loginInfo'))
//予約内容を保存するstate変数
const [appo, setAppo] = useState({
docNum :'',
memNum: loginInfo ? loginInfo.memNum : "", //ログインしたメンバーの情報
deptNum :1 , //診療科目は昇順にした
schDate: moment(value).format("YYYY-MM-DD"),
schTime : '',
detail:'',
deptName:'',
to_email : '' //これは予約メールを送るために(ここでは紹介していない)
})
})
次は診療科と日付、時間をすべて選択した後の画面です。左側で予約日を選択すると、右側の画面に私が選択した情報と私の情報も一緒に入力されていることを確認できます。
このようにリアルタイム予約機能の実装を完成させました。
この他にも、メール送信や必須入力項目をすべて入力しないと警告メッセージが表示されるなどの機能を実装しました。予約画面をこのように締めくくりたいと思います。
プロジェクトを終えて..
このプロジェクトは私の初めてのプロジェクトでしたが、Reactカレンダーを使うことができて良かったです。ライブラリの使い方をよく知らなかったので、最初は検索するのに非常に多くの時間を費やさなければなりませんでしたが、一度完成させてしまえば、次回はあまり迷わずに済むと思います。
Discussion