ポートフォリオで予約サイトを作りました

## はじめに
転職を目的として、未経験からスクールでプログラミングの学習を行った際に制作したポートフォリオです。
学習期間は約4か月、そのうちポートフォリオ制作には1ヶ月半ほどかけています。

また、前職がネットショップだったこともあり、考えやすいだろうと思って予約サイトを制作することにしました。
制作の中で、個人的にこだわったポイントをまとめて紹介します。

## ポートフォリオのテーマ
<b>「お花屋さん発信型のフラワーアレンジメントや花束の予約サイト」</b>
お客さんが、複数あるショップから商品を選んで予約する、<b>お花屋さん限定のモール</b>というイメージです。

## このテーマを選んだ理由
友人がお花屋さんで働いており、お花のアレンジメントや花束などを当日急に来店されたお客さんから注文されると、事前に準備することもできず焦ってしまって大変だという話を聞きました。
また、私自身、花束などを購入したことがなかったとき、どうやって予約や購入をすればいいのか悩んだ経験があります。

お店とお客さん、お互いにすれ違ってしまっているな…と感じたため、お花屋さん側が花束やアレンジメントを紹介して、お客さん側がそれを気軽に予約出来るサイトがあれば、双方の問題を解決できると考え、このテーマを選びました。​

## このサイトで出来ること
ユーザーは「お花屋さん」「お客さん」「管理者」の3パターンです。
ログイン状況が分かりやすいように、それぞれのヘッダーやフッターなどのメインカラーを変えています。

### お客さん(一般ユーザ)

* <b>商品を選んで予約をする</b>

![商品の予約_2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762011/8198d0f7-04e8-9202-e789-22aa04298c51.gif)

予約には会員登録が必要です。（気軽に予約やキャンセルが出来ないように）
商品一覧から商品を予約しますが、ログイン前に見ていた商品を予約したい場合もあると考えたため、マイページの<b>「最近見た商品」</b>で<b>ログイン前に見た商品が表示</b>されるようにしました。

また、サンプルにはのせていませんが、予約中にリロードしたりブラウザバックしたりしても情報が消えないように商品データをsessionで渡しています。

* <b>予約状況が来店済みになったら口コミが投稿できる</b>

![口コミ投稿.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762011/d7aebc5c-7733-a13c-0d28-ad73a6993b7a.gif)
不適切な口コミをなるべく防げるように、
来店済みだと、「投稿できる」
予約中もしくはキャンセルだと、「投稿できない」
来店して2週間過ぎると、「投稿できない（期限切れ）」
という投稿制限を設けています。

また、口コミの投稿を促すため、口コミを投稿できる予約が存在している場合は、マイページにも表示されます。


### お花屋さん(ショップユーザ)

* <b>商品を登録して予約を受け付ける</b>

![商品の編集.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762011/a7ea0db1-8858-5935-d997-3e0315b84401.gif)
ミスを減らすため、重要な金額などの<b>商品情報を登録する画面</b>と<b>商品の詳細画像を編集する画面</b>は分けています。
商品詳細画像は確認がしやすいように<b>プレビューページで編集する</b>ことができ、サンプルにはのせていませんが、画像の追加や並び替えも行うことができます。

ちなみに、商品は予約と紐づけられているので、1度でも予約の入ったことがある商品は、非公開にはできるけど削除はできない設定になっています。


<b>※画像の判定</b>
![商品画像の判定.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762011/5cacf4a9-52e4-ca99-bcdf-660e7983a8ec.gif)
登録された画像は、Google Cloud Vision APIによって、お花や植物に関連しているかどうかの判定を行っています。
関連性がない可能性のある画像が登録された際は警告文が出て、サイト管理者側にも確認を促すようにしています。

※これは、複数のショップユーザーが存在するという特性上、間違いやいたずら防止として設置してみましたが、風景などでもOK判定になってしまったりと、設定がゆるくて精度はあまり良くないので一応設置したという形になっています。

↓詳しくはこちらの記事に記載あり

https://qiita.com/plant0322/items/670ab8a99a09efb0b00f

* <b>予約状況を確認して編集する</b>

![予約状況の変更.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762011/0a84c45a-5e0e-2190-dfc0-b8e34102b5fe.gif)
予約管理画面には
<b>「現在の予約」</b>欄に<b>「予約中」</b>の予約情報が表示され、
<b>「過去の予約履歴」</b>欄に<b>「来店済み」</b>や<b>「キャンセル」</b>の予約情報が表示されます。
<b>「予約中」</b>のお客さんが来店し、予約状況を<b>「来店済み」</b>に変更することで予約の管理を行うことが出来ます。


* <b>お客さんの問い合わせに答える</b>

![メッセージのやり取り.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762011/e0201775-ab25-cd53-5806-14e60853d43e.gif)
商品に対する問い合わせがしやすいように、お客さんはそれぞれのショップの詳細ページからショップへメッセージを送ることが出来るようになっています。

メッセージの返信漏れをなくすための目印として、ショップ側の一覧ではお客さんからメッセージが届くと<b>「対応待ち」</b>の表示になり、対応が完了した際に<b>「対応済み」</b>に変更することが出来ます。

<a href ="https://qiita.com/plant0322/items/f637d8894a227b02c157">【Rails6.1】同じUser同士じゃない場合のDM機能（課題は残る）</a>


### サイト管理者
* <b>タグの管理をする</b>

![タグ管理.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762011/5f30fe2a-f9ef-2d50-7e8e-293c63f041a2.gif)
サイトTOPでは、画面が単調にならないように<b>スライド式のイベント画像を表示</b>しています。
これは、サイト管理者が登録できるイベントページで、既に登録されているタグ情報と紐づけることで作成することが出来ます。（お花は季節のイベントも重要なので）

このイベントページのリンクは、スライド画像だけでなく、左ナビの<b>「おすすめ商品」</b>にも同じ内容が表示されます。
また、<b>「タグ管理」</b>ページでは、登録されたイベントの編集や並び替えもできます。
たとえば、母の日のイベントを時期が過ぎたら非公開にしておき、また季節がやってきたら公開して上位に表示させるということも可能です。

ちなみに左ナビの<b>「人気商品」</b>は、たくさん使われているタグの上位10件が表示されるようになっています。
<a href ="https://qiita.com/plant0322/items/3402cb32e586e33d4529">【Rails6】紐づいた商品の数が多い上位10件のタグ名を並べたい</a>

また、タグは商品を登録する際にショップが追加する仕組みになっているため、管理者画面では登録されているタグの一覧を確認して、不適切な内容は削除することが出来ます。


* <b>投稿された商品の内容を確認して承認/承認不可の設定、公開/非公開の設定</b>

![商品画像の判定管理者.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762011/1cc5422e-977c-5a78-4dca-9c9d3324bb6a.gif)
管理者側では登録されている全ての商品を確認することが出来ます。
Google Cloud Vision APIによって、ショップ側で不適切な画像を登録された可能性があると判定されると、ここの「画像チェック」欄が「確認中」になります。

不適切な商品の登録があった際に、管理者側でここから強制的に「公開/非公開」に設定を変えることもできます。

* <b>口コミの投稿内容を確認して公開/非公開の設定</b>

![口コミ確認.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762011/ad61d8d3-dcb4-4840-a594-34361cbebccc.gif)
こちらはGoogle Natural Language APIを使用して、口コミの内容が攻撃的でないかどうかをパッと見で確認できるようにしています。
また、ショップで口コミを操作できると情報が偏る可能性もあると感じたので、口コミの非公開設定は管理者側からしか行えないようにしています。
そのため、口コミの内容判定数値も管理者側にのみ表示されます。

## スマホ表示
スマホやタブレットで開いた際にも、表示が崩れないようにレイアウトの調整を行いました。
サンプルはショップでログインした際の表示です。
![2024-08-25_22-24-34.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762011/ea46a938-9294-e0ca-b205-c16e4d3236cf.gif)
ヘッダーが広すぎるとか、上にスクロールしたときハンバーガーメニューくらいは表示したいとか、メッセージ機能のレイアウトどうにかならないかとか、いろいろ思うところはありますが、一般ユーザーとショップユーザーの画面はスマホでも比較的扱いやすくなるように調整しました。
ちなみに、サイト管理者はPCで作業するだろうと想定してあまり丁寧に整えてはいません。


## 意識したポイント
### 直感的に使いやすい工夫
* ボタンの配置やサイズ感を踏まえた押しやすさ
* ボタンの色分けによる動線整備
* リンク部分のマウスオーバー（PC）

### 運営を意識した設定
* TOPが単調にならないよう、定期的に変更できるイベント画像の設置
* ブックマークやお気に入り追加は簡単に、削除は少しだけ不便に
* ショップの予約履歴検索はユーザー情報だけでなく商品情報でも検索可に
* 在庫切れの場合は動線確保のため商品詳細にショップの新着商品を表示
* パンくずの設置（構造化データ）

### おっちょこちょい対策
* 商品情報と詳細の登録箇所を分ける（間違い防止のため）
* 商品削除のルール（予約が入っていたら削除できない）
* キャンセル期限以内ならユーザー側からキャンセルできる（無断キャンセル防止のため）
<a href ="https://qiita.com/plant0322/items/776373ab90d60d9d6f02">【Bootstrap5.3】キャンセル機能をモーダルで</a>

### ユーザーに合わせた使い勝手の追求
* お店にPCがない場合もあるので、スマホでも見やすくなるようにレスポンシブ表示
* ログイン前に見ていた商品が購入できるように、最近見た商品をマイページに表示
* 一覧は新着順ではなく更新順（商品ページの再利用がしやすいように）

### その他
* ショップユーザーとサイト管理者との権限の住み分け
* ラジオボタンの微調整（検索後にチェックが外れないように）
<a href ="https://qiita.com/plant0322/items/ff19815402aa8e02bfcc">【Rails6】ラジオボタンの使いづらさ解消 ＆ Bootstrap5.3を使ったレイアウト調整</a>
* 画像を軽くするためWebpを使用
<a href ="https://qiita.com/plant0322/items/5b4845132a6c67818711">画像をリサイズしてから登録した時の話</a>
<a href ="https://qiita.com/plant0322/items/59f104a5306f1b2c30f6">画像表示をwebpにした時の話</a>



<a href="https://qiita.com/plant0322/items/f8828da2987a5b74235c">【Rails6】ちょっとだけややこしかったタグ検索機能の実装</a>

### レイアウト関連
<a href ="https://qiita.com/plant0322/items/05ecaad35dd45be41a16">【Rails6.1】kaminariを使ったページネーションのレイアウトとか</a>
<a href ="https://qiita.com/plant0322/items/5e0c61d5dd9d9b56adc6">【Rails6.1】2種類のレイアウトを使ったブックマークを非同期にする方法</a>
<a href ="https://qiita.com/plant0322/items/ec0f9224c368ff06796a">【固定リンク】商品詳細の右下にページ内リンクを設置する</a>



## ER図
![ER図_flower_match-ER図.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762011/ed2f5299-5e58-fa47-21ed-891068d22f27.png)


## 使用技術
### Gem
* ユーザー認証(devise)
* 画像アップロード時のサイズと解像度の変更(MiniMagick)
* ショップ所在地の都道府県登録と検索(JpPrefecture)
* ページネーション(kaminari)

### その他
* 画像アップロード機能(Active Storage)
* ブックマーク追加の非同期通信(Ajax)
* ショップお気に入り追加の非同期通信(Ajax)
* 商品画像の関連性判定(Google Vision API)
* 口コミのポジティブ判定(Google Natural Language API)


### 開発環境
* OS：Linux(CentOS)
* 言語：HTML,CSS,JavaScript,Ruby,SQL
* フレームワーク：Ruby on Rails
* JSライブラリ：jQuery
* IDE：Cloud9​

### 使用素材
* 商品画像：Canva
* アイコン：Font Awesome

## おわりに
やりたいことや気になる部分がありすぎて、制作中はとんでもなく忙しかったです。

また、ネットショップで働いていた際に感じていた、
人的ミスはレイアウトを変えるだけでけっこう激減する、
複雑な機能は個人の能力に影響されるから扱いづらい、
目的に合わせた設計や配置が必要、
といった点も意識したポートフォリオを作ることが出来たと思います。

まだまだ気になる部分はたくさんありますが、コンセプトに対する熱量が高かったこともあり、とてもお気に入りの作品になりました。