前回までの状況はこちら
最新ソースはこちら(gitHub)
https://github.com/takishita2nd/hotel-mng
さて、前回はユーザーログインでのあれこれを修正したのですが、それに伴って、管理者ログインでのあれもれも直す必要があります。
まずは、予約一覧画面。
ユーザーログインでは、ログインしたユーザーのもののみを表示させましたが、管理者ログインでは、全ユーザーの情報を表示する必要があります。
なので、ロール「管理者(manager)」でなければwhere句でユーザーを指定するというふうに変えなければなりません。
public function getListByMonth($year, $month, $room, $userId)
{
$select = ['reserve_managements.id as id', 'users.name as name', 'users.address as address', 'users.phone as phone', 'num', 'rooms.id as roomid', 'rooms.name as room', 'days', 'checkout', 'start_day'];
$query = ReserveManagement::select($select)
->leftJoin('reserve_management_room', 'reserve_managements.id', '=', 'reserve_management_room.reserve_management_id')
->leftJoin('rooms', 'reserve_management_room.room_id', '=', 'rooms.id')
->leftJoin('reserve_management_user', 'reserve_managements.id', '=', 'reserve_management_user.reserve_management_id')
->leftJoin('users', 'reserve_management_user.user_id', '=', 'users.id')
->where('start_day', '>=', date('Y-m-d', strtotime('first day of '.$year.'-'.$month)))
->where('start_day', '<=', date('Y-m-d', strtotime('last day of '.$year.'-'.$month)))
->where('reserve_management_room.room_id', $room)
->where('lodging', false);
if(Gate::denies('manager')){
$query = $query->where('users.id', $userId);
}
$query = $query->orderBy('start_day');
return $query->get();
}
こんな感じで、where()を、Gate::denies()で「管理者以外」とすれば、このwhereはユーザーログインのみに適用されます。
次は、予約追加画面。
ユーザーログインの場合は、ログイン中の名前などの表示させましたが、管理者ログインの場合は、登録されているユーザーを選択して登録しなければなりません。
ここでVue.jsの出番です。(まじか・・・)
まずはテンプレート。
基本的には、編集時のVue.jsを参考にしています。
<template>
<div>
<p v-if="error_flg == true" class="error">{{error_message}}</p>
<table class="edit">
<tbody>
<tr>
<th>名前</th>
<td v-if=role>{{ contents.name }}<button @click="openModal">検索</button></td>
<td v-else>{{ contents.name }}</td>
</tr>
<tr>
<th>住所</th>
<td>{{ contents.address }}</td>
</tr>
<tr>
<th>電話番号</th>
<td>{{ contents.phone }}</td>
</tr>
<tr>
<th>人数</th>
<td>
<select v-model=contents.num>
<option v-for="num in nums" v-bind:value="num.value">{{ num.text }}</option>
</select>
</td>
</tr>
<tr>
<th>宿泊部屋</th>
<td>
<select v-model="contents.roomid">
<option v-for="room in rooms" v-bind:value="room.id">{{ room.name }}</option>
</select>
</td>
</tr>
<tr>
<th>宿泊日数</th>
<td><input type="number" v-model=contents.days /></td>
</tr>
<tr>
<th>宿泊日</th>
<td><input type="date" v-model=contents.start_day /></td>
</tr>
<tr>
<th>チェックアウト</th>
<td>
<select v-model="contents.checkout">
<option v-for="time in timeList" v-bind:value="time.key">{{ time.value }}</option>
</select>
</td>
</tr>
</tbody>
</table>
<p><button @click="regist">登録</button></p>
<div id="overlay" v-show="showContent">
<div id="content">
<table class="edit">
<p>名前<input type="text" v-model=param.search /></p>
<tbody>
<tr>
<th>名前</th>
<th>住所</th>
<th>電話番号</th>
</tr>
<tr v-for="user in users" @click="selectUser(user)">
<td class="name">{{ user.name }}</td>
<td class="address">{{ user.address }}</td>
<td class="phone">{{ user.phone }}</td>
</tr>
</tbody>
</table>
<p>
<button @click="closeModal">close</button>
<button @click="searchUsers">検索</button>
</p>
</div>
</div>
</div>
</template>
まず、テーブルの部分ですが、名前、住所、電話番号以外は、編集画面をそのまま使用しました。
問題の、名前、住所、電話番号の部分ですが、管理者ログインならば、検索ボタンを設置し、それをクリックするとモーダルダイアログを表示する、という仕組みにしたいと思います。
モーダルダイアログでユーザーを検索し、その名前をクリックすると、登録画面に反映される、という動きにします。
実際の処理。
<script>
export default {
data() {
return {
role: false,
error_message: "",
error_flg:false,
errors: {},
nums: [
{text:'1', value:1},
{text:'2', value:2}
],
timeList:[],
rooms: [],
users: [],
showContent: false,
param: {
search: "",
},
contents: {
id: 0,
name: "",
address: "",
phone: "",
num: 0,
roomid: 0,
room: "",
days: 0,
start_day: "",
checkout: "",
},
}
},
created: function() {
this.getRole();
this.getRooms();
this.getTimeList();
},
methods: {
getRole: function() {
var self = this;
axios.post('/api/role').then(function(response){
self.role = response.data.role;
if(self.role == false){
self.contents.id = response.data.user.id;
self.contents.name = response.data.user.name;
self.contents.address = response.data.user.address;
self.contents.phone = response.data.user.phone;
}
}).catch(function(error){
console.log("失敗しました");
});
},
searchUsers: function() {
this.users = [];
var self = this;
axios.post('/api/users', this.param).then(function(response){
response.data.users.forEach(element => {
self.users.push({id:element.id, name:element.name, address:element.address, phone:element.phone});
});
}).catch(function(error){
console.log("失敗しました");
});
},
selectUser: function(user) {
this.contents.id = user.id;
this.contents.name = user.name;
this.contents.address = user.address;
this.contents.phone = user.phone;
this.closeModal();
},
regist: function() {
var self = this;
this.param.contents = this.contents;
axios.post('/api/add', this.param).then(function(response){
document.location = "/management";
}).catch(function(error){
self.error_flg = true;
self.error_message = error.response.data.errors;
console.log("失敗しました");
});
},
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("失敗しました");
});
},
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("失敗しました");
});
},
openModal: function(){
this.users = [];
this.showContent = true;
},
closeModal: function(){
this.showContent = false;
this.edit_flg = false;
},
}
}
</script>
ポイントは、ユーザーログインも管理者ログインも使用するということ。
なので、現在ログインしているアカウントのロールをgetRole()で最初に取得している、ということです。
このgetRole()の結果で表示内容を切り替えたりしてます。
そして、必要事項を入力したら、登録処理を行います。
このとき必要になるのは、ユーザーID。これも送信するパラメータに含めます。
では、API側の処理。
public function __construct()
{
$this->middleware('auth');
$this->registerManagement = new RegisterManagementRepository();
$this->room = new RoomRepository();
$this->user = new UserRepository();
}
public function role(Request $request)
{
return response()->json(['role' => Gate::Allows('manager'),
'user' => Auth::user()]);
}
public function users(Request $request)
{
return response()->json(['users' => $this->user->search($request->search)]);
}
public function add(Request $request)
{
\Log::debug(print_r($request->contents, true));
if($this->registerManagement->checkSchedule($request->contents["start_day"],
$request->contents["days"],
$request->contents["roomid"]) == false)
{
return response()->json([
'errors' => "スケジュールが重複しています"
], 400);
}
$param = $this->registerManagement->getParam();
$this->registerManagement->add([
$param[0] => $request->contents["num"],
$param[1] => $request->contents["days"],
$param[2] => $request->contents["start_day"],
$param[3] => false,
$param[4] => date('Y-m-d H:i', strtotime($request->contents["start_day"].' + '.$request->contents["days"].' day') + $request->contents["checkout"])
], $request->contents["roomid"], $this->user->getUserById($request->contents["id"]));
return response()->json();
}
class UserRepository
{
public function __construct()
{
}
public function getUserById($id)
{
return User::where("id", $id)->first();
}
public function search($word)
{
$select = ['id', 'name', 'address', 'phone'];
return User::select($select)
->where('name', 'like', "%{$word}%")
->get();
}
}
ユーザー検索で使用する「あいまい検索」はこんな感じで「like」を使用します。
管理者ログイン時の動作
ユーザーログイン時の動作
これでうまく行ったみたいです。(疲れた。。。)