自動見積もりフォーム

vue.jsフレームワーク

  1. HOME
  2. 自動見積

自動見積もりフォーム

動画発表の日にちを選択してください
仕上がり予定日を発表日の1週間前に設定しております
オリジナル楽曲を依頼される場合は1曲{{taxedopt1 | number_format}}円かかります
メイキングムービーを依頼される場合の料金です
盤面デザインを希望される場合は{{taxedopt3 | number_format}}円(税込)がかかります
プリントアウトした写真のスキャニング希望の方は1枚当たり{{taxedopt4 | number_format}}円にて承ります

データの持たせ方

No 変数名 データ型 説明
1 taxRate 数値 消費税率
2 movieType 文字列 制作したいムービーの種類
3 basePrice 数値 基本料金(税込)
4 addPrice1 数値 納期が1カ月未満の割増料金
5 addPrice2 数値 納期が3週間未満の割増料金
6 addPrice3 数値 納期が2週間未満の割増料金
7 addPrice4 数値 納期が1週間未満の割増料金
8 addPrice5 数値 納期が3日後の割増料金
9 addPrice6 数値 納期が2日後の割増料金
10 addPrice7 数値 納期が翌日の割増料金
11 optPrice/td> 数値 オプション料金の合計(税込)
12 totalPrice 数値 合計金額(税込)
13 announcement_date 文字列 発表日(書式:YYYY-MM-DD)
14 delivery_date 文字列 DVD仕上がり予定日(書式:YYYY-MM-DD)
15 opt1_use 真偽値 BGM制作依頼のありなし
16 opt1_price 数値 BGM制作の税込料金
17 opt2_use 真偽値 メイキング撮影のありなし
18 opt2_price 数値 メイキング撮影の税込料金
19 opt3_use 真偽値 DVD盤面印刷のありなし
20 opt3_price 数値 DVD盤面印刷の税込料金
21 opt4_num 数値 スキャニング写真の利用枚数
22 opt4_price 数値 スキャニング写真の税込料金
日付の差を求めるgetDateDiff()関数は、methodsオプションにメソッドとして定義します。
dataオプションのプロパティや、算出プロパティ、メソッドなどは同じコンポーネント内ならthisで参照できます。

通貨書式のフィルターは汎用的なのでグローバルスコープに登録。グローバルに登録するフィルターの定義はコンポーネントよりも先に記述する必要がある。

HTML

<div id="app" v-cloak>
<div class="container bg-dark text-white p-5">
  <h2 class="text-center border-bottom pb-3 mb-5">自動見積もりフォーム</h2>
  <form>
    <div class="form-group row">
      <label class="col-md-3 col-form-label pt-0">希望する動画制作
        <span class="badge badge-danger">必須</span>
      </label>
      <div class="col-md-9">
        <div class="row">
          <div class="col-md-5">
            <div class="form-check form-check-inline">
              <input class="form-check-input" type="radio" name="movie_type" id="type1" value="余興ムービー" v-model="movieType">
              <label class="form-check-label" for="type1">余興ムービー</label>
            </div>
          </div><!-- col-md-5 -->
          <div class="col-md-5">
            <div class="form-check form-check-inline">
              <input class="form-check-input" type="radio" name="movie_type" id="type2" value="広告用ムービー" v-model="movieType">
              <label class="form-check-label" for="type2">広告用ムービー</label>
            </div>
          </div><!-- col-md-5 -->
          <div class="col-md-5">
            <div class="form-check form-check-inline">
              <input class="form-check-input" type="radio" name="movie_type" id="type3" value="プレゼン動画" v-model="movieType">
              <label class="form-check-label" for="type3">プレゼン動画</label>
            </div>
          </div><!-- col-md-5 -->
          <div class="col-md-5">
            <div class="form-check form-check-inline">
              <input class="form-check-input" type="radio" name="movie_type" id="type4" value="会社紹介動画" v-model="movieType">
              <label class="form-check-label" for="type4">会社紹介動画</label>
            </div>
          </div><!-- col-md-5 -->
        </div>
      </div>
    </div>
    <!-- 発表日 -->
    <div class="form-group row">
      <label class="col-md-3 col-form-label pt-0" for="announcement_date">発表日
        <span class="badge badge-danger">必須</span>
      </label>
      <div class="col-md-9">
        <input class="form-control" type="date" id="announcement_date" placeholder="日付を選びください" v-model="announcement_date">
        <small class="form-text">動画発表の日にちを選択してください</small>
      </div>
    </div>
    <!-- DVD仕上がり予定日 -->
    <div class="form-group row">
      <label class="col-md-3 col-form-label pt-0" for="delivery_date">DVD納品予定日
        <span class="badge badge-danger">必須</span>
      </label>
      <div class="col-md-9">
        <input class="form-control" type="date" id="delivery_date" v-bind:min="tommorow" placeholder="日付を選びください" v-model="delivery_date">
        <small class="form-text">仕上がり予定日を発表日の1週間前に設定しております</small>
      </div>
    </div>
    <!-- 基本料金 -->
    <div class="form-group row">
      <label class="col-md-3 col-form-label pt-0">基本料金(税込)</label>
      <div class="col-md-9">
        <div class="input-group">
          <input type="text" class="form-control text-right" id="sum_base" v-bind:value="taxedBasePrice | number_format" readonly>
          <div class="input-group-append">
            <label class="input-group-text">円</label>
          </div>
        </div>
      </div>
    </div>
    <!-- オプションメニュー -->
    <div class="form-group row">
      <label class="col-md-3 col-form-label pt-0">オプション(税込)
        <span class="badge badge-info">任意</span>
      </label>
      <div class="col-md-9">
        <div class="form-check mb-3">
          <input class="form-check-input" type="checkbox" id="opt1" v-model="opt1_use">
          <label class="form-check-label" for="opt1">BGM制作 +{{taxedopt1 | number_format}}円</label>
          <small class="form-text">オリジナル楽曲を依頼される場合は1曲{{taxedopt1 | number_format}}円かかります</small>
        </div>
        <div class="form-check mb-3">
          <input class="form-check-input" type="checkbox" id="opt2" v-model="opt2_use">
          <label class="form-check-label" for="opt2">メイキング動画 +{{taxedopt2 | number_format}}円</label>
          <small class="form-text">メイキングムービーを依頼される場合の料金です</small>
        </div>
        <div class="form-check mb-3">
          <input class="form-check-input" type="checkbox" id="opt3" v-model="opt3_use">
          <label class="form-check-label" for="opt3">DVD盤面印刷 +{{taxedopt3 | number_format}}円</label>
          <small class="form-text">盤面デザインを希望される場合は{{taxedopt3 | number_format}}円(税込)がかかります</small>
        </div>
        <div class="form-row mb-3 align-items-center">
          <div class="col-auto">
            <label class="form-check-label" for="opt4">写真スキャニング +{{taxedopt4 | number_format}}円</label>
          </div>
          <div class="col-auto">
            <div class="input-group">
              <input class="form-control" type="number" id="opt4" v-model.number="opt4_num" min="0" max="30">
              <div class="input-group-append">
                <label class="input-group-text" for="opt4">枚</label>
              </div>
            </div>
          </div>
          <small class="form-text">プリントアウトした写真のスキャニング希望の方は1枚当たり{{taxedopt4 | number_format}}円にて承ります</small>
        </div>
      </div>
    </div>
    <!-- 小計 -->
    <div class="form-group row">
      <label class="col-md-3 col-form-label pt-0">オプション料金(税込)</label>
      <div class="col-md-9">
        <div class="input-group">
          <input type="text" class="form-control text-right" id="sum_opt" v-bind:value="taxedOptPrice | number_format" readonly>
          <div class="input-group-append">
            <label class="input-group-text">円</label>
          </div>
        </div>
      </div>
    </div>
    <!-- 合計 -->
    <div class="form-group row">
      <label class="col-md-3 col-form-label pt-0">合計(税込)</label>
      <div class="col-md-9">
        <div class="input-group">
          <input type="text" class="fo-m-control text-right" id="sum_total" v-bind:value="taxedTotalPrice | number_format" readonly>
          <div class="input-group-append">
            <label class="input-group-text">円</label>
          </div>
        </div>
      </div>
    </div>
  </form>
</div>
</div><!-- /#app -->

JavaScript

//通貨書式への変換フィルター
Vue.filter('number_format', function (val) {
  return val.toLocaleString();
});

var app = new Vue({
  el: '#app',
  data: {
    taxRate: 0.1,
    movieType: '余興ムービー',
    basePrice: 25000,
    addPrice1: 5000,
    addPrice2: 10000,
    addPrice3: 15000,
    addPrice4: 20000,
    addPrice5: 30000,
    addPrice6: 40000,
    addPrice7: 45000,
    optPrice: 0,
    totalPrice: 0,
    announcement_date: '',
    delivery_date: '',
    opt1_use: false,
    opt1_price: 6600,
    opt2_use: false,
    opt2_price: 12500,
    opt3_use: false,
    opt3_price: 1200,
    opt4_num: 0,
    opt4_price: 320,
  },
  methods: {
    //税込金額に変換
    incTax: function (untaxed) {
      return Math.floor(untaxed * (1 + this.taxRate));
    },
    //日付の差分を求める
    getDateDiff: function (dateString1, dateString2) {
      var date1 = new Date(dateString1);
      var date2 = new Date(dateString2);
      //二つの日付の差分(ミリ秒)を計算
      var msDiff = date1.getTime() - date2.getTime();
      //差分を日付に変換 差分÷(1000ミリ秒×60秒×60分×24時間)
      return Math.ceil(msDiff / (1000 * 60 * 60 * 24));
    },
    //日付をYYYY-MM-DDの書式を返すメソッド
    formatDate: function (dt) {
      var y = dt.getFullYear();
      var m = ('00' + (dt.getMonth() + 1)).slice(-2);
      var d = ('00' + dt.getDate()).slice(-2);
      return (y + '-' + m + '-' + d);
    }
  },
  computed: {
    taxedopt1: function () {
      return this.incTax(this.opt1_price);
    },
    taxedopt2: function () {
      return this.incTax(this.opt2_price);
    },
    taxedopt3: function () {
      return this.incTax(this.opt3_price);
    },
    taxedopt4: function () {
      return this.incTax(this.opt4_price);
    },
    taxedBasePrice: function () {
      var addPrice = 0;
      //納期までの残り日数
      var dateDiff = this.getDateDiff(this.delivery_date, (new Date()).toLocaleString());
      //割増料金
      if (21 <= dateDiff && dateDiff < 30) {
        addPrice = this.addPrice1;
      } else if (14 <= dateDiff && dateDiff < 21) {
        addPrice = this.addPrice2;
      } else if (7 <= dateDiff && dateDiff < 14) {
        addPrice = this.addPrice3;
      } else if (3 <= dateDiff && dateDiff < 7) {
        addPrice = this.addPrice4;
      } else if (dateDiff == 3) {
        addPrice = this.addPrice5;
      } else if (dateDiff == 2) {
        addPrice = this.addPrice6;
      } else if (dateDiff == 1) {
        addPrice = this.addPrice7;
      }
      return this.incTax(this.basePrice + addPrice);
    },
    taxedOptPrice: function () {
      var optPrice = 0;
      if (this.opt1_use) { optPrice += this.opt1_price; }
      if (this.opt2_use) { optPrice += this.opt2_price; }
      if (this.opt3_use) { optPrice += this.opt3_price; }
      if (this.opt4_num == '') { this.opt4_num == 0; }
      optPrice += this.opt4_num * this.opt4_price;
      return this.incTax(optPrice);
    },
    taxedTotalPrice: function () {
      return (this.taxedBasePrice + this.taxedOptPrice);
    },
  },
  created: function () {
    //今日の日付取得
    var dt = new Date();
    //発表日に2か月後の日付を初期設定
    dt.setMonth(dt.getMonth() + 2);
    this.announcement_date = this.formatDate(dt);
    //DVD納品予定日をさらに1週間前に初期設定
    dt.setDate(dt.getDate() - 7);
    this.delivery_date = this.formatDate(dt);
  },
  //明日の日付をYYYY-MM-DDの書式で返すプロパティ
  tommorow: function () {
    var dt = new Date();
    dt.setDate(dt.getDate() + 1);
    return this.formatDate(dt);
  }
});