React-Leafletを使って座席管理システムを作る

# 機能追加
https://qiita.com/y_nomura_kawaii_komugi/items/64093b9f52910dba5d5c
機能追加してます。


# 参考記事
こちらの記事を参考にしました。

https://qiita.com/kanaxx/items/c846c049af46ae4cdac3

https://engineering.linecorp.com/ja/blog/floor-map-management-system-on-web-with-leaflet

# はじめに
きっかけは弊社の座席管理方法でした。
令和にもなって座席の管理はパワーポイントで行われていました。
参考にしたLINEの記事でも同様の記述がありましたが
座席情報の信頼性が薄く、急な出社となっても本当に空席があるかわかりませんでした。
また来週、来月の座席情報がないため、仮に来月から自社に戻るとなっても
一言添えたうえでパワーポイントを更新するしかありませんでした。
このことから信頼性と即時性を備えたWebシステムの座席管理が必要という結論に至りました。

# 開発に至る経緯
理由は三つあります。
一つ目は無料で自分が欲しい機能がある座席管理システムがなかったことです。
座席管理システムでググってもらうとわかりますが
無料トライアルはあっても永年無料なんてものは見つかりませんでした。

二つ目は自身の学習のためです。
最初に挙げた記事のものを使っても良かったのですが
個人的にReactを学習したかったのでReact-Leafletを使ってシステムを構築したかったのです。
しかしReact-Leafletを使ったシステムを記事等がなかったため開発に至りました。

三つ目は座席予約を期間指定できるシステムにしたかったためです。
これは参考にした記事にはない機能でした。

# できたもの
結果こんな感じのものができあがりました。

左上のセレクトボックスでフロアと日付を切り替えることができて
その日の座席情報を知ることができます。
また期間指定ではなく固定席を登録することもできます。

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546752/b701151c-5c70-e8e2-158e-1ab37228b744.png)
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546752/916b6537-a6f9-9ad3-cc93-794407446336.png)
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546752/ae385dcf-e6cc-e2ec-c00f-02e38ba12c4f.png)
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546752/8a0661c9-35ac-7b47-9b4b-70cefffda337.png)
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546752/209febcf-2a76-3284-a8c2-ca344fbd1255.png)

# できないこと
- 時間指定の座席予約（13時～15時とかの指定はできません。日単位）
- ~~座席の追加（DBから直接ポチポチする必要があります）~~　管理モードを追加しました
- オフィスの追加（DBから直接ポチポチ、画像を自分で加工する必要があります）
- 期間指定の座席の削除（この日からこの日の座席を一気に空席に、ということはできません）
- 権限判定（誰でも座席を空席にすることができます）


# 技術要素
- React-Leaflet
- Express
- Sqlite3

ReactのフロントサイドとExpress＋Sqlite3のサーバサイドに分かれています。
ReactもExpressも初挑戦で苦戦しました。
初挑戦のためコードが汚い点はご容赦ください。

# コード
コードはgithubで公開しています。

https://github.com/nomura565/seat-reservation-app-front

https://github.com/nomura565/seat-reservation-app-rest-api

# 使い方
コードをcloneして`npm start`すれば動くはずです。
あとは自分のオフィスに合わせて設定を変えてください。

1\. オフィス画像の変更
seat-reservation-app-front\public\office.pngを変更してください。
seat-reservation-app-front\public\office.xlsxのテンプレートを参考にすることもできます。
1100×620の画像であれば大丈夫です。

2\. フロアマスタの変更
seat-reservation-app-rest-api\app\db\sqlite3-database.dbの
floor_masterを変更してください。
同フォルダのcsvからインポートしても良いです。

3\. 座席マスタの変更
seat-reservation-app-rest-api\app\db\sqlite3-database.dbの
seat_masterを変更してください。
同フォルダのcsvからインポートしても良いです。
座席マスタの緯度経度は配置したい場所をクリックするとコンソールに出るようになっていますのでその値をマスタの緯度経度に入力しましょう。
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546752/9dff67bc-e86c-391d-00cf-cec8390fdc11.png)

# 苦戦したところ
主にReact-Leaflet部分で苦戦しました。

- React-Leafletだとmapオブジェクトをどうやって参照するのか？
座席をクリックしたとき、地図を座席が中心になるように移動させたい。
Leafletだとこんな感じでdivのIDからオブジェクトを指定できるがReactだと・・・？？？
```js:
var mapobj = L.map('mapDiv',{zoomControl:false});
mapobj.setView([35.36063,138.72731],10);
```

正解はUseMap。
```js:
const parentMap = useMap();
parentMap.setView(e.popup._latlng, parentMap.getZoom());
```


- 座席をクリックしてポップアップが開いたときのイベントをどうやって取得するのか？
ポップアップが開いたときに前述のように地図を座席が中心になるように移動させたい。
これも普通だとonでバインドできるがReactだと・・・？？？？

```js:
map.on('popupopen', function(e) {
  // PopupEvent e
  // e.type
  // e.target
  // e.sourceTarget
  // e.popup
});
```

正解はuseMapEvents。

```js:
const mapEvents = useMapEvents({
  popupopen(e) {
    setTimeout(function(){
      parentMap.setView(e.popup._latlng, parentMap.getZoom());
    }, 10);
  }
})
```

ほかにもいろんなところで悩みましたが割愛します。

# まとめ
些細な部分で悩むことが多かったですが
Reactの理解も深まって結果的に想定通りのものができて良かったと思います。

座席の追加、オフィスの追加は時間があれば管理モードを実装したいところ。