まぁ、つまらないものですが

エンジニニャーの気ままな技術ブログ、日々のログを残してゆきます。

学校の学祭向けにPOSっぽいシステムのフロントの実装をした話

大遅刻その2
とりあえず前のが長文だったので軽いのを一つ書こうと思います。

内容としては以下のブログのフロントエンド側の話です。

mi-neko-maple.hatenablog.com

大急ぎで作ってろくにコメントも残してなかったのでその解説をします。

今回のいきさつ

自分は殆ど学校にいないので学祭に関しては極力2年1年で行ってほしいと思い内容に関与は極力避けてました。
会計のシステムに関しては一年生が行うということで様子を見ていたのですが、一ヶ月でAndroid上にシステムを作るということで流石に勉強しながら難しいく感じたので自分も手伝うことにしました。
とりあえずシステムをWebアプリに変更し実装をフロントとバックに分け担当の子がGoogleAppsScriptの経験があるということでバックエンドの処理を任せ自分はフロントエンドを実装することにしました。

今回の仕様と制約

仕様

  • タッチをしたら購入リストに足される
  • 足された合計が常に表示されている
  • 会計ボタンを押すと会計内容が表示されエンドポイントにJSONで購入リストが送られる

制約(縛りプレイ内容)

  • 極力Vue.jsやReact、PHPRubyを使わずJSとJqueryのみを使って実装する
    • 来年再利用する際に覚えることを少なくさせるため 開発環境の構築が楽なように
  • モバイルのブラウザ上で動く
    • レスポンシブなページでトリッキーなことをしない
  • できるだけ早く行う

実際できたもの

ほんとに簡素なものですが…

コードの解説

2-10行

itemList = {
  '0':{'name': 'プリン', 'price':120, 'type':'food', 'postName': 'pudding'},
  '1':{'name': 'レアチーズケーキ', 'price':120, 'type': 'food', 'postName': 'cake'},
  '2':{'name': '珈琲', 'price':120, 'type': 'drink', 'postName': 'coffee'},
  '3':{'name': '紅茶', 'price':120, 'type': 'drink', 'postName': 'straighttea'},
  '4':{'name': 'Dr.Prepper', 'price':150, 'type': 'drink', 'postName': 'drpepper'}
};

ココらへんは連想配列で商品を定義しています。ホントは商品リストを取得するAPIを作っていただいたのでつなぎ込みしたかったのですが、ギリギリで間に合わず…
先頭から表示名、値段、商品区別、商品英字名(POST時に使う)

11-22行

postBody = {
'total':0,
'deposit':0,
'set':0,
'pudding':0,
'jelly':0,
'cake':0,
'coffee':0,
'milktea':0,
'straighttea':0,
'drpepper':0
};

こちらは送る時に使う配列をゼロ埋めして定義します。実際にAPIに投げる時使用します

showItem()

function showItem(){

  Object.keys(itemList).forEach(function(val, int, array){
     $("#itemList").prepend(makeCard(itemList[val], int)).hide().fadeIn(1000);
  });

itemListを順々に呼び出しそれをmakeCard関数に投げて実際に表示するHTMLを

というタグに追加します。

makeCard(val, idx)

function makeCard(val, idx){
  console.log(val);
  return '<div style="padding-top: 25px" class="col-md-2"  >\
    <div class="demo-card-wide mdl-card mdl-shadow--2dp"  onClick="selectItem('+ idx +')">\
      <div class="mdl-card__title  mdlcard--border">\
        <h2 class="mdl-card__title-text">'+ val.name +'</h2>\
      </div>\
      <div class="mdl-card__supporting-text ">'+ val.price + '円 </div>\
      <div class="mdl-card__menu">\
        <div id="tt4" class="icon material-icons">share</div>\
        <div class="mdl-tooltip" for="tt4">\
          Twitterに投稿\
      </div>\
      </div>\
    </div>\
  </div>  ';

実際に表示するHTMLに各情報を埋め込んでいきます。今回はMaterialUIというCSSフレームワークを用いてカード上のUIにしています。
ポイントなのはDiv内にあるonClick="selectItem('+ idx +')"です。
カードをonClickはクリックされた時に中に書かれている処理を実行します。 中にあるTwitterに投稿は消し忘れでした。

selectItem(itemId)

itemListのキーをmakeCardのonClick内にうめこんでいたのを引数として処理を行います。処理後商品リストと合算をHTMLで表示します。

  selectItemList.push(itemId);

ここで選択したものリストに選択したものを追加します。

insertHtml = "";
  totalPrice = 0;
  setNum = {"food": 0, "drink": 0 }

  selectItemList.forEach(function(val, int, array){
  insertHtml += itemList[val]['name']+ ":" +itemList[val]['price'] + "<br>";
  totalPrice += itemList[val]['price'];

  // セット判定(ドクペ以外ならフラグを立てる)
  if(val < 4){
    if(itemList[val]['type'] == 'food'){
      setNum['food'] = setNum['food']+1;
    }else{
      setNum['drink'] = setNum['drink']+1;
    }
  }
});

  setCount = 0;
  if(setNum['food'] < setNum['drink']){
    setCount = setNum['food'] ;
  }else{
    setCount = setNum['drink'] ;
  }

  if(setCount > 0){
    insertHtml +=  "セット割引" + -40 * setCount +  "<br>";
    totalPrice -= 40 * setCount;

  }


  insertHtml += "合計 :" + totalPrice;
  console.log(insertHtml);
  console.log(setNum);
  $("#selectItems").html(insertHtml).hide().fadeIn(1000);
   $("#checkPrace").html(insertHtml).hide().fadeIn(1000);

ここは選択した商品リストから食べ物と飲み物の購入数をカウントし割引が適用出来るかどうかを判定して値段を計算しています。

  // セット判定(ドクペ以外ならフラグを立てる)
  if(val < 4){
    if(itemList[val]['type'] == 'food'){
      setNum['food'] = setNum['food']+1;
    }else{
      setNum['drink'] = setNum['drink']+1;
    }
  }

selectItemListの中を順々に呼び出してここでカウントしています。もっと簡素な書き方もありますが、わかりやすさ優先で書いてます。

  setCount = 0;
  if(setNum['food'] < setNum['drink']){
    setCount = setNum['food'] ;
  }else{
    setCount = setNum['drink'] ;
  }

  if(setCount > 0){
    insertHtml +=  "セット割引" + -40 * setCount +  "<br>";
    totalPrice -= 40 * setCount;

  }

ここではセット数をカウントし割引価格を適用しています。
食べ物と飲み物を比較して少ない方をセット数として適用しています。

 insertHtml += "合計 :" + totalPrice;
  console.log(insertHtml);
  console.log(setNum);
  $("#selectItems").html(insertHtml).hide().fadeIn(1000);
   $("#checkPrace").html(insertHtml).hide().fadeIn(1000);

ここで最終的な値段とHTMLに埋め込みjQueryを通して表示しています。

postItem()

決済ボタンを押された時に呼び出される関数です。
データを整形してAJAXと呼ばれる形式でサーバーに送信します。
ホントはそのままAPIに送りたかったけど右往左往あって一度PHPに投げてPHPで再度送信してます。
なんでこんなめんどくさい形式にしたんだっけ…?

色々と思うこと

チーム開発でいきなり看板管理やGithubを使ったGithubFlowとかいろいろやってもらおうと思うけどだいたい時間とか説明不足とかでうまくできず申し訳ありませんでした。
ただ、ここらへんは弊学では授業で行わない範囲なのでこういうところこそYMIC PGが積極的にやっていってほしいなぁと思います。
また後輩指導の難しさを改めて感じるプロジェクトでした。 なかなか頼りになる先輩になるには先が長そうです。残り学校生活は少ないですが、今後も山本五十六提督の「やってみせ、言って聞かせて、させてみせ、ほめてやらねば、人は動かじ」を実践できるよう頑張っていく所存でございます。
まずは何卒弊学AdventCalendarをよろしくお願いします。

相互リンク

  • 技術ブログ:ヤモト.tvp
  • 友人氏の技術ブログ 数学ガチ勢がエンジニアになっていく奮闘記