前回までの状況はこちら
前回の予約詳細画面。
これに、編集ボタンを追加して、予約編集できるようにします。
これが思いの外大変だった。
まずはテンプレートを編集。
<div id="overlay" v-show="showContent">
<div id="content">
<p v-if="error_flg == true" class="error">{{error_message}}</p>
<table class="edit">
<tbody>
<tr>
<th>名前</th>
<td v-if="edit_flg == true"><input type="text" v-model=contents.name /></td>
<td v-else>{{ contents.name }}</td>
</tr>
<tr>
<th>住所</th>
<td v-if="edit_flg == true"><input type="text" v-model=contents.address /></td>
<td v-else>{{ contents.address }}</td>
</tr>
<tr>
<th>電話番号</th>
<td v-if="edit_flg == true"><input type="text" v-model=contents.phone /></td>
<td v-else>{{ contents.phone }}</td>
</tr>
<tr>
<th>人数</th>
<td v-if="edit_flg == true">
<select v-model=contents.num>
<option v-for="num in nums" v-bind:value="num.value">{{ num.text }}</option>
</select>
</td>
<td v-else>{{ contents.num }}</td>
</tr>
<tr>
<th>宿泊部屋</th>
<td v-if="edit_flg == true">
<select v-model="contents.roomid">
<option v-for="room in rooms" v-bind:value="room.id">{{ room.name }}</option>
</select>
</td>
<td v-else>{{ contents.room }}</td>
</tr>
<tr>
<th>宿泊日数</th>
<td v-if="edit_flg == true"><input type="number" v-model=contents.days /></td>
<td v-else>{{ contents.days }}</td>
</tr>
<tr>
<th>宿泊日</th>
<td v-if="edit_flg == true"><input type="date" v-model=contents.start_day /></td>
<td v-else>{{ contents.start_day }}</td>
</tr>
<tr>
<th>チェックアウト</th>
<td v-if="edit_flg == true">
<select v-model="contents.checkout">
<option v-for="time in timeList" v-bind:value="time.key">{{ time.value }}</option>
</select>
<td v-else>{{ contents.checkout }}</td>
</tr>
</tbody>
</table>
<p>
<button @click="closeModal">close</button>
<button v-if="edit_flg == false" @click="onClickEdit">編集</button>
<button v-else @click="onClickSave">保存</button>
</p>
</div>
</div>
edit_flgという状態変数を見て、これがtrueならば、タグをinputに置き換える、という作りになっています。
では、データの方はというと、
data() {
return {
error_message: "",
error_flg:false,
errors: {},
中略
nums: [
{text:'1', value:1},
{text:'2', value:2}
],
timeList:[],
selectRoom: 0,
rooms: [],
result: [],
param: {
year: 2019,
month: 1,
room: 1
},
registers: [],
showContent: false,
contents: {
name: "",
address: "",
phone: "",
num: 0,
roomid: 0,
room: "",
days: 0,
start_day: "",
checkout: "",
},
edit_flg: false
}
},
ポイントはedit_flg。これをtrueにすることで、テンプレートが編集用に置き換わります。
なお、編集中のテンプレートは、予約追加時と同じくらいの機能を持たなくてはいけません。
もう、予約追加処理も、この中に入れてしまってもいいのかもしれない。
実際の処理は、
created: function() {
this.getRooms();
this.getTimeList();
},
methods: {
getRooms: function() {
var self = this;
axios.post('/api/rooms').then(function(response){
response.data.roomLists.forEach(element => {
self.rooms.push({id:element.id, name:element.name});
});
}).catch(function(error){
console.log("失敗しました");
});
},
getRegisters: function() {
var self = this;
this.param.year = this.selectYear;
this.param.month = this.selectMonth;
this.param.room = this.selectRoom;
axios.post('/api/registers', this.param).then(function(response){
self.registers = [];
response.data.registerLists.forEach(element => {
self.registers.push(
{
id:element.id,
name:element.name,
address:element.address,
phone:element.phone,
num:element.num,
roomid:element.roomid,
room:element.room,
days:element.days,
start_day:element.start_day,
checkout:element.checkout
}
);
});
}).catch(function(error){
console.log("失敗しました");
});
},
onClickEdit: function(){
this.edit_flg = true;
var checkoutTime = this.contents.checkout.split(" ")[1];
this.timeList.forEach(element => {
if(checkoutTime == element.value+":00"){
this.contents.checkout = element.key;
}
});
},
onClickSave: function(){
var self = this;
this.param.year = this.selectYear;
this.param.month = this.selectMonth;
this.param.room = this.selectRoom;
this.param.contents = this.contents;
axios.post('/api/update', this.param).then(function(response){
self.registers = [];
response.data.registerLists.forEach(element => {
self.registers.push(
{
id:element.id,
name:element.name,
address:element.address,
phone:element.phone,
num:element.num,
roomid:element.roomid,
room:element.room,
days:element.days,
start_day:element.start_day,
checkout:element.checkout
}
);
});
self.closeModal();
}).catch(function(error){
self.error_flg = true;
self.error_message = error.response.data.errors;
});
},
openModal: function(id){
for(var i = 0; i< this.registers.length; i++){
if(this.registers[i].id == id){
this.contents.id = this.registers[i].id;
this.contents.name = this.registers[i].name;
this.contents.address = this.registers[i].address;
this.contents.phone = this.registers[i].phone;
this.contents.num = this.registers[i].num;
this.contents.roomid = this.registers[i].roomid;
this.contents.room = this.registers[i].room;
this.contents.days = this.registers[i].days;
this.contents.start_day = this.registers[i].start_day;
this.contents.checkout = this.registers[i].checkout;
break;
}
}
this.showContent = true;
this.edit_flg = false;
},
closeModal: function(){
this.showContent = false;
this.edit_flg = false;
},
getTimeList: function(){
var self = this;
axios.post('/api/timelist').then(function(response){
for (let [key, value] of Object.entries(response.data.timelist)){
self.timeList.push({key: key, value: value});
}
}).catch(function(error){
console.log("失敗しました");
});
}
onClickEdit()で、詳細画面から、編集画面に切り替わります。
そして、onClickSave()で、入力したデータをLaravel側のAPI処理にデータを渡します。
うん、予約追加もこの中でいいよね。
あと、サーバ側でエラーが発生した場合のメッセージ表示も追加しています。
error_flgがtureになったらテンプレートにもその要素が表示され、API側で送られたメッセージが画面に表示されます。
では、API側の処理。
ルーティングに以下を追加します。
Route::post('/api/update', 'ApiController@update');
Route::post('/api/timelist', 'ApiController@timelist');
処理は、
public function timelist(Request $request)
{
return response()->json(['timelist' => $this->registerManagement->getTimeList()]);
}
public function update(Request $request)
{
\Log::debug(print_r($request->contents, true));
if($this->registerManagement->checkScheduleForUpdate($request->contents["start_day"],
$request->contents["days"],
$request->contents["id"],
$request->contents["roomid"]) == false)
{
\Log::debug("スケジュールが重複しています");
return response()->json([
'errors' => "スケジュールが重複しています"
], 400);
}
$param = $this->registerManagement->getParam();
$this->registerManagement->updateById($request->contents["id"],
[
$param[0] => $request->contents["name"],
$param[1] => $request->contents["address"],
$param[2] => $request->contents["phone"],
$param[3] => $request->contents["num"],
$param[4] => $request->contents["days"],
$param[5] => $request->contents["start_day"],
$param[6] => false,
$param[7] => date('Y-m-d H:i', strtotime($request->contents["start_day"].' + '.$request->contents["days"].' day') + $request->contents["checkout"])
], $request->contents["roomid"]);
return response()->json(['registerLists' => $this->registerManagement->getListByMonth(
$request->year,
$request->month,
$request->room
)]);
}
timelist()というのは、データベースで処理するtick値と画面に表示する時刻のテーブルです。
これがあるためにつまずいた。
tick: “時刻(00:00)”
という形でデータを持っていたために、これがうまくVueで処理されないので、JavaScriptで形を変換したのですよ。
このやり方を見つけるのに苦労した・・・。
getTimeList: function(){
var self = this;
axios.post('/api/timelist').then(function(response){
for (let [key, value] of Object.entries(response.data.timelist)){
self.timeList.push({key: key, value: value});
}
}).catch(function(error){
console.log("失敗しました");
});
}
ここの処理ね、
[{tick: “時刻(00:00)”},{ },・・・]
このフォーマットを
[{key:tick, value:”時刻”},{ },・・・}
に変換したのですよ。
これを導き出すのに苦労しました。
でも、これができれば今までのサーバ側の処理が、ほぼ、そのまま使えるわけで、
編集画面でも、予約追加と同じことができるようになりました。
っていうか、追加処理もこの形にしよう。
ってなことで次回。
「【Laravel】【Vue.js】【ホテル予約管理】予約の編集を行う」への1件のフィードバック