Laravel mixでDateTimePicker(tempusdominus v5 → v6)にアップデートする

# 環境

* Laravel 8.x
* Laravel Mix v6
* tempusdominus v5(tempusdominus-bootstrap-4のv5.x) → tempusdominus v6(@eonasdan/tempus-dominus)にアップデート
    * popper.js v2(tempusdominus v6依存)
    * fontawesome v6(tempusdominus v6で利用)
* npm 11.x

# Laravel Mix設定

## npmコマンド(ライブラリインストール)

```shell
# tempusdominus-bootstrap-4のアンインストール
npm uninstall tempusdominus-bootstrap-4

# tempus-dominus(v6)とpopperjs(v2)のインストール
npm i --save-dev @popperjs/core @eonasdan/tempus-dominus

# fontawesome(v6)のインストール
npm i --save-dev @fortawesome/fontawesome-free
```

## Laravel Mix設定

↓特に変更なし
```webpack.mix.js
const mix = require('laravel-mix');

/*
 |--------------------------------------------------------------------------
 | Mix Asset Management
 |--------------------------------------------------------------------------
 |
 | Mix provides a clean, fluent API for defining some Webpack build steps
 | for your Laravel application. By default, we are compiling the Sass
 | file for the application as well as bundling up all the JS files.
 |
 */

mix.js('resources/js/app.js', 'public/js').vue()
    .sass('resources/sass/app.scss', 'public/css');

if (mix.inProduction()) {
    mix.version();
}
```

### tempusdominus v6設定

```resources/js/bootstrap.js
// --- Tempus Dominus Date/Time Picker
window.tempusDominus = require('@eonasdan/tempus-dominus');
// 下記でapp.jsに含めると、日付入力時に1度画面上部に飛ばされる動作をするため、含めない(popper.jsの(v1)と(v2)を両方使ってるからかも？)
// window.Popper = require('@popperjs/core');
```

```resources/sass/app.scss
// Font Awesome
@import '~@fortawesome/fontawesome-free/scss/fontawesome';
@import '~@fortawesome/fontawesome-free/scss/solid';
@import '~@fortawesome/fontawesome-free/scss/regular';
@import '~@fortawesome/fontawesome-free/scss/brands';

// Tempus Dominus Date/Time Picker
@import '~@eonasdan/tempus-dominus/src/scss/tempus-dominus';
```

## npmコマンド(app.js, app.cssの最新化)

```shell
# app.js, app.cssの最新化
npm run prod
```

# 画面

```html
<head>
    <!-- Styles -->
    <link href="{{ url('/') }}{{ mix('css/app.css') }}" rel="stylesheet">
    <!-- Scripts -->
    <script src="{{ url('/') }}{{ mix('/js/app.js') }}"></script>

    {{-- (下記は Tempus Dominus Date/Time Pickerで使用。app.jsに含めず npm run prodすると707.jsで出力された --}}
    <!-- @popperjs/core Scripts -->
    <script src="{{ asset('js/707.js') }}?version={{ filemtime(public_path() . "/js/707.js") }}"></script>
</head>

<style type="text/css">
<!--
/* Tempus Dominus Date/Time Picker
------------------------------------- */
/* DateTimePickerの土日 */
.date-container-days div.dow {
    color: #000 !important;
    font-weight: bold;
}
.date-container-days div.dow:first-child {
    color: #c42626 !important;
}
.date-container-days div.dow:nth-child(7) {
    color: #005dbf !important;
}
.date-container-days div.day.weekend {
    color: #c42626;
}
.date-container-days div.day:nth-child(7n) {
    color: #005dbf;
}
.date-container-days div.day.old.weekend,
.date-container-days div.day.new.weekend {
    color: #00000060;
}

/* sideBySideの時間を縦中央表示 */
.tempus-dominus-widget.timepicker-sbs .td-row {
    display: flex;
    align-items: center;
}
-->
</style>

<div class="input-group" id="date" data-target-input="nearest">
    <input class="form-control datetimepicker-input" type="text" name="date" value="{{$date}}" data-target="#date">
    <div class="input-group-append" data-target="#date" data-toggle="datetimepicker">
        <div class="input-group-text"><i class="fa-regular fa-clock"></i></div>
    </div>
</div>
{{-- DateTimePicker 呼び出し --}}
@include('plugins.common.datetimepicker', ['element_id' => "date", 'side_by_side' => true])
```

```html:resources/views/plugins/common/datetimepicker.blade.php
@php
    // TempusDominusの設定
    $element_id = $element_id ?? null;
    $side_by_side = $side_by_side ?? false;
    $format = $format ?? 'yyyy-MM-dd HH:mm';
    $date = $date ?? true;
    $seconds = $seconds ?? false;
    $clock_icon = $clock_icon ?? true;
    $calendar_icon = $calendar_icon ?? true;
    $stepping = $stepping ?? 1;
    $view_mode = $view_mode ?? 'calendar';

    // 設定のみオプション
    $is_setting_only = $is_setting_only ?? false;
@endphp

<script type="text/javascript">
    const picker_setting_{{$element_id}} = {
        localization: {
            locale: '{{ App::getLocale() }}',
            dayViewHeaderFormat: { year: 'numeric', month: 'long' },
            format: '{{$format}}',
            @if (App::getLocale() == ConnectLocale::ja)
                today: '本日',
                close: '閉じる',
                selectMonth: '月を選択',
                previousMonth: '前月',
                nextMonth: '次月',
                selectYear: '年を選択',
                previousYear: '前年',
                nextYear: '次年',
                selectDecade: '期間を選択',
                previousDecade: '前期間',
                nextDecade: '次期間',
                previousCentury: '前世紀',
                nextCentury: '次世紀',
                pickHour: '時間を取得',
                incrementHour: '時間を増加',
                decrementHour: '時間を減少',
                pickMinute: '分を取得',
                incrementMinute: '分を増加',
                decrementMinute: '分を減少',
                pickSecond: '秒を取得',
                incrementSecond: '秒を増加',
                decrementSecond: '秒を減少',
                toggleMeridiem: '午前/午後切替',
                selectTime: '時間を選択',
            @endif
        },
        display: {
            viewMode: '{{$view_mode}}',
            components: {
                @if (!$date)
                    date: false,
                @endif
                @if ($seconds)
                    seconds: true,
                @endif
                @if (!$clock_icon)
                    clock: false,
                @endif
                @if (!$calendar_icon)
                    calendar: false,
                @endif
            },
            @if ($side_by_side)
                sideBySide: true,
            @endif
            theme: 'light',
        },
        stepping: {{$stepping}},
    }

    @if (!$is_setting_only)
        const picker_{{$element_id}} = new tempusDominus.TempusDominus(document.getElementById('{{$element_id}}'), picker_setting_{{$element_id}});
    @endif
</script>
```

## 画面イメージ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109904/5beb0fee-3aba-438e-8e2f-9ab7c419112c.png)

# 参考

* tempusdominus v6
    * Options - Tempus Dominus
https://getdatepicker.com/6/options/
    * Download - Tempus Dominus
https://getdatepicker.com/6/installing.html
      * > (機械翻訳) ファイルの取得方法に関係なく、ピッカーのメインスクリプトファイルの前に【Popper】が含まれていることを確認してください。
また、フォントライブラリも必要になります。ピッカーの既定値は 【Font Awesome 6】 ですが、別のアイコン セットを指定できます 設定またはプラグインを介して。
    * Bootstrap 5でDateTimePicker(tempusdominus v6)を使いたい #DatePicker - Qiita
https://qiita.com/yaju/items/247813a10546353bd7c8
* popper.js v2 + Laravel Mixで導入
  * javascript - How do I add popper.js to a Laravel 8 with Bootstrap 5 project? - Stack Overflow
https://stackoverflow.com/questions/71537172/how-do-i-add-popper-js-to-a-laravel-8-with-bootstrap-5-project
      * > window.Popper = require('@popperjs/core');

# 所感

laravel mixでtempusdominus6の導入方法の記事がパッと見、見当たらなかったため、記事化しました。