Explore all Datepicker open source software, libraries, packages, source code, cloud functions and APIs.

Popular New Releases in Datepicker

ng-bootstrap

12.0.1

react-datepicker

4.6.0

ngx-bootstrap

v8.0.0

AndroidPicker

4.1.6

react-day-picker

v8.0.4

Popular Libraries in Datepicker

Android-PickerView

by Bigkoo doticonjavadoticon

star image 12799 doticonApache-2.0

This is a picker view for android , support linkage effect, timepicker and optionspicker.(时间选择器、省市区三级联动)

react-dates

by airbnb doticonjavascriptdoticon

star image 11488 doticonMIT

An easily internationalizable, mobile-friendly datepicker library for the web

ng-bootstrap

by ng-bootstrap doticontypescriptdoticon

star image 7904 doticonMIT

Angular powered Bootstrap

pickadate.js

by amsul doticonjavascriptdoticon

star image 7749 doticonMIT

The mobile-friendly, responsive, and lightweight jQuery date & time input picker.

react-datepicker

by Hacker0x01 doticonjavascriptdoticon

star image 6462 doticonMIT

A simple and reusable datepicker component for React

ngx-bootstrap

by valor-software doticontypescriptdoticon

star image 5363 doticonMIT

Fast and reliable Bootstrap widgets in Angular (supports Ivy engine)

AndroidPicker

by gzu-liyujiang doticonjavadoticon

star image 5358 doticonNOASSERTION

安卓选择器类库,包括日期及时间选择器(可用于出生日期、营业时间等)、单项选择器(可用于性别、民族、职业、学历、星座等)、二三级联动选择器(可用于车牌号、基金定投日期等)、城市地址选择器(分省级、地市级及区县级)、数字选择器(可用于年龄、身高、体重、温度等)、日历选日期择器(可用于酒店及机票预定日期)、颜色选择器、文件及目录选择器、图片选择器等……WheelPicker/DatePicker/TimePicker/OptionPicker/NumberPicker/LinkagePicker/AddressPicker/CarPlatePicker/CalendarPicker/ColorPicker/FilePicker/ImagePicker etc.

react-day-picker

by gpbl doticontypescriptdoticon

star image 4465 doticonMIT

Date picker component for React.

react-infinite-calendar

by clauderic doticonjavascriptdoticon

star image 3776 doticonMIT

✨ Infinite scrolling date-picker built with React, with localization, range selection, themes, keyboard support, and more.

Trending New libraries in Datepicker

DateTimePicker

by loperSeven doticonkotlindoticon

star image 644 doticon

:star::tada:一个高颜值日期时间选择器;极简API,内置弹窗,支持农历日期显示,可动态配置样式及主题,选择器支持完全自定义UI。

MDatePickerView

by MattLLLLL doticonswiftdoticon

star image 378 doticonMIT

Quick and easy date picker.

XPopupExt

by li-xiaojun doticonjavadoticon

star image 133 doticon

XPopup扩展功能库,基于XPopup强大的弹窗能力和PickerView的选择器逻辑,封装了时间选择器弹窗和城市选择器弹窗。

react-multi-date-picker

by shahabyazdi doticonjavascriptdoticon

star image 109 doticonMIT

a simple React datepicker component for working with gregorian, persian, arabic and indian calendars

SharpChisel

by shantanu561993 doticongodoticon

star image 96 doticon

C# Wrapper around Chisel from https://github.com/jpillora/chisel

persian-mobile-datepicker

by persian-tools doticontypescriptdoticon

star image 80 doticonMIT

Modern React Persian Mobile Date and Time picker

better-datepicker

by jumodada doticontypescriptdoticon

star image 64 doticonMIT

A PC Datepicker with only 9KB

react-native-jalali-datepicker

by MohamadKh75 doticonjavascriptdoticon

star image 53 doticonMIT

📅 React Native Jalali DatePicker component for both Android and iOS ✨

react-jewish-datepicker

by Shmulik-Kravitz doticontypescriptdoticon

star image 35 doticonGPL-3.0

React jewish datepicker

Top Authors in Datepicker

1

rajeshwarpatlolla

3 Libraries

star icon700

2

kekeh

3 Libraries

star icon838

3

Velg03961485

2 Libraries

star icon5

4

saeidrnb

2 Libraries

star icon34

5

nathancahill

2 Libraries

star icon7

6

contao-components

2 Libraries

star icon8

7

zigomir

2 Libraries

star icon142

8

Gillardo

2 Libraries

star icon340

9

sinankeskin

2 Libraries

star icon8

10

jkuri

2 Libraries

star icon93

1

3 Libraries

star icon700

2

3 Libraries

star icon838

3

2 Libraries

star icon5

4

2 Libraries

star icon34

5

2 Libraries

star icon7

6

2 Libraries

star icon8

7

2 Libraries

star icon142

8

2 Libraries

star icon340

9

2 Libraries

star icon8

10

2 Libraries

star icon93

Trending Kits in Datepicker

No Trending Kits are available at this moment for Datepicker

Trending Discussions on Datepicker

Datepicker not working / showing - Bootstrap 5

The unauthenticated git protocol on port 9418 is no longer supported

How to change the date picker from spinner to calendar dialogue in Android Kotlin

Use selected element when selector allow for multiple options

Dynamic form returns the same value for the first and second input

Pass data from the model to js for a specific day and time

Module not found: Error: Can't resolve 'date-fns/addDays' in 'C:\Users\

Why does MUI DatePicker prevent rendering in my project (working sandbox MRE included?)

Using the MUI DatePicker with yup and react-hook-form - the error prop doesn't work as intended

JavaFX: Exception in Application Start Method java.lang.reflect.InvocationTargetException

QUESTION

Datepicker not working / showing - Bootstrap 5

Asked 2022-Apr-05 at 03:48

I am trying to add a timepicker to my page using bootstrap 5, for some reason the calendar is not loading so I can not pick any date. I do not know if I have done something wrong or the plugin is not compatible with the latest version of bootstrap.

If you click 'launch demo modal' you will see the date input field and datepicker is not working there.

enter image description here

This is the code for the input date field:

1<div class="col-12">
2    <label for="date" class="col-sm-1 col-form-label">Date</label>
3    <div class="input-group date" id="datepicker">
4        <input type="text" class="form-control">
5        <span class="input-group-append">
6        <span class="input-group-text bg-white d-block">
7        <i class="fa fa-calendar"></i>
8        </span>
9        </span>
10    </div>
11</div>    
12

JS (truncated):

1<div class="col-12">
2    <label for="date" class="col-sm-1 col-form-label">Date</label>
3    <div class="input-group date" id="datepicker">
4        <input type="text" class="form-control">
5        <span class="input-group-append">
6        <span class="input-group-text bg-white d-block">
7        <i class="fa fa-calendar"></i>
8        </span>
9        </span>
10    </div>
11</div>    
12<script type="text/javascript">
13    $(document).ready(function () {
14        $('#datepicker').datepicker();
15        ...
16    });
17</script>      
18

I also tried using $('.datepicker').datepicker(); according to the bootstrap-datepicker docs but nothing changed.

ANSWER

Answered 2021-Oct-29 at 06:00

Demo page

Stackoverflow source

You should put bootstrap-datepicker.min.js after jquery.js. It somehow make errors because of that.

1<div class="col-12">
2    <label for="date" class="col-sm-1 col-form-label">Date</label>
3    <div class="input-group date" id="datepicker">
4        <input type="text" class="form-control">
5        <span class="input-group-append">
6        <span class="input-group-text bg-white d-block">
7        <i class="fa fa-calendar"></i>
8        </span>
9        </span>
10    </div>
11</div>    
12<script type="text/javascript">
13    $(document).ready(function () {
14        $('#datepicker').datepicker();
15        ...
16    });
17</script>      
18<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.9.0/js/bootstrap-datepicker.min.js"></script>
19

Source https://stackoverflow.com/questions/69764102

QUESTION

The unauthenticated git protocol on port 9418 is no longer supported

Asked 2022-Mar-27 at 13:23

I have been using github actions for quite sometime but today my deployments started failing. Below is the error from github action logs

1Command: git
2Arguments: ls-remote --tags --heads git://github.com/adobe-webplatform/eve.git
3Directory: /home/runner/work/stackstream-fe/stackstream-fe
4Output:
5fatal: remote error: 
6  The unauthenticated git protocol on port 9418 is no longer supported.
7

Upon investigation, it appears that below section in my yml file is causing the issue.

1Command: git
2Arguments: ls-remote --tags --heads git://github.com/adobe-webplatform/eve.git
3Directory: /home/runner/work/stackstream-fe/stackstream-fe
4Output:
5fatal: remote error: 
6  The unauthenticated git protocol on port 9418 is no longer supported.
7    - name: Installing modules
8      run: yarn install
9

I have looked into this change log but can't seem to comprehend the issue.

Additional Details: Server: EC2 Instance Github actions steps:

1Command: git
2Arguments: ls-remote --tags --heads git://github.com/adobe-webplatform/eve.git
3Directory: /home/runner/work/stackstream-fe/stackstream-fe
4Output:
5fatal: remote error: 
6  The unauthenticated git protocol on port 9418 is no longer supported.
7    - name: Installing modules
8      run: yarn install
9  steps:
10  - name: Checkout
11    uses: actions/checkout@v2
12
13  - id: vars
14    run: |
15      if [ '${{ github.ref }}' == 'refs/heads/master' ]; then echo "::set-output name=environment::prod_stackstream" ; echo "::set-output name=api-url::api" ; elif [ '${{ github.ref }}' == 'refs/heads/staging' ]; then echo "::set-output name=environment::staging_stackstream"  ; echo "::set-output name=api-url::stagingapi" ; else echo "::set-output name=environment::dev_stackstream" ; echo "::set-output name=api-url::devapi" ; fi
16
17  - uses: pCYSl5EDgo/cat@master
18    id: slack
19    with:
20      path: .github/workflows/slack.txt
21
22  - name: Slack Start Notification
23    uses: 8398a7/action-slack@v3
24    env:
25      SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
26      ENVIRONMENT: '`${{ steps.vars.outputs.environment }}`'
27      COLOR: good
28      STATUS: '`Started`'
29    with:
30      status: custom
31      fields: workflow,job,commit,repo,ref,author,took
32      custom_payload: |
33        ${{ steps.slack.outputs.text }}
34
35  - name: Installing modules
36    env:
37      REACT_APP_API_URL: 'https://${{ steps.vars.outputs.api-url }}mergestack.com/api/v1'
38    run: yarn install
39
40  - name: Create Frontend Build
41    env:
42      REACT_APP_API_URL: 'https://${{ steps.vars.outputs.api-url }}mergestack.com/api/v1'
43    run: yarn build
44
45  - name: Deploy to Frontend Server DEV
46    if: ${{ contains(github.ref, 'dev') }}
47    uses: easingthemes/ssh-deploy@v2.1.5
48    env:
49      SSH_PRIVATE_KEY: ${{ secrets.DEV_KEY }}
50      ARGS: '-rltgoDzvO --delete'
51      SOURCE: 'deploy/'
52      REMOTE_HOST: ${{ secrets.DEV_HOST }}
53      REMOTE_USER: plyfolio-dev
54      TARGET: '/home/plyfolio-dev/${{ steps.vars.outputs.environment }}/fe/deploy'
55

package.json file

1Command: git
2Arguments: ls-remote --tags --heads git://github.com/adobe-webplatform/eve.git
3Directory: /home/runner/work/stackstream-fe/stackstream-fe
4Output:
5fatal: remote error: 
6  The unauthenticated git protocol on port 9418 is no longer supported.
7    - name: Installing modules
8      run: yarn install
9  steps:
10  - name: Checkout
11    uses: actions/checkout@v2
12
13  - id: vars
14    run: |
15      if [ '${{ github.ref }}' == 'refs/heads/master' ]; then echo "::set-output name=environment::prod_stackstream" ; echo "::set-output name=api-url::api" ; elif [ '${{ github.ref }}' == 'refs/heads/staging' ]; then echo "::set-output name=environment::staging_stackstream"  ; echo "::set-output name=api-url::stagingapi" ; else echo "::set-output name=environment::dev_stackstream" ; echo "::set-output name=api-url::devapi" ; fi
16
17  - uses: pCYSl5EDgo/cat@master
18    id: slack
19    with:
20      path: .github/workflows/slack.txt
21
22  - name: Slack Start Notification
23    uses: 8398a7/action-slack@v3
24    env:
25      SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
26      ENVIRONMENT: '`${{ steps.vars.outputs.environment }}`'
27      COLOR: good
28      STATUS: '`Started`'
29    with:
30      status: custom
31      fields: workflow,job,commit,repo,ref,author,took
32      custom_payload: |
33        ${{ steps.slack.outputs.text }}
34
35  - name: Installing modules
36    env:
37      REACT_APP_API_URL: 'https://${{ steps.vars.outputs.api-url }}mergestack.com/api/v1'
38    run: yarn install
39
40  - name: Create Frontend Build
41    env:
42      REACT_APP_API_URL: 'https://${{ steps.vars.outputs.api-url }}mergestack.com/api/v1'
43    run: yarn build
44
45  - name: Deploy to Frontend Server DEV
46    if: ${{ contains(github.ref, 'dev') }}
47    uses: easingthemes/ssh-deploy@v2.1.5
48    env:
49      SSH_PRIVATE_KEY: ${{ secrets.DEV_KEY }}
50      ARGS: '-rltgoDzvO --delete'
51      SOURCE: 'deploy/'
52      REMOTE_HOST: ${{ secrets.DEV_HOST }}
53      REMOTE_USER: plyfolio-dev
54      TARGET: '/home/plyfolio-dev/${{ steps.vars.outputs.environment }}/fe/deploy'
55   {
56  "name": "stackstream-fe",
57  "version": "1.0.0",
58  "authors": [
59    "fayyaznofal@gmail.com"
60  ],
61  "private": true,
62  "dependencies": {
63    "@fortawesome/fontawesome-svg-core": "^1.2.34",
64    "@fortawesome/free-solid-svg-icons": "^5.15.2",
65    "@fortawesome/react-fontawesome": "^0.1.14",
66    "@fullcalendar/bootstrap": "^5.5.0",
67    "@fullcalendar/core": "^5.5.0",
68    "@fullcalendar/daygrid": "^5.5.0",
69    "@fullcalendar/interaction": "^5.5.0",
70    "@fullcalendar/react": "^5.5.0",
71    "@lourenci/react-kanban": "^2.1.0",
72    "@redux-saga/simple-saga-monitor": "^1.1.2",
73    "@testing-library/jest-dom": "^5.11.9",
74    "@testing-library/react": "^11.2.3",
75    "@testing-library/user-event": "^12.6.0",
76    "@toast-ui/react-chart": "^1.0.2",
77    "@types/jest": "^26.0.14",
78    "@types/node": "^14.10.3",
79    "@types/react": "^16.9.49",
80    "@types/react-dom": "^16.9.8",
81    "@vtaits/react-color-picker": "^0.1.1",
82    "apexcharts": "^3.23.1",
83    "availity-reactstrap-validation": "^2.7.0",
84    "axios": "^0.21.1",
85    "axios-mock-adapter": "^1.19.0",
86    "axios-progress-bar": "^1.2.0",
87    "bootstrap": "^5.0.0-beta2",
88    "chart.js": "^2.9.4",
89    "chartist": "^0.11.4",
90    "classnames": "^2.2.6",
91    "components": "^0.1.0",
92    "dotenv": "^8.2.0",
93    "draft-js": "^0.11.7",
94    "echarts": "^4.9.0",
95    "echarts-for-react": "^2.0.16",
96    "firebase": "^8.2.3",
97    "google-maps-react": "^2.0.6",
98    "history": "^4.10.1",
99    "i": "^0.3.6",
100    "i18next": "^19.8.4",
101    "i18next-browser-languagedetector": "^6.0.1",
102    "jsonwebtoken": "^8.5.1",
103    "leaflet": "^1.7.1",
104    "lodash": "^4.17.21",
105    "lodash.clonedeep": "^4.5.0",
106    "lodash.get": "^4.4.2",
107    "metismenujs": "^1.2.1",
108    "mkdirp": "^1.0.4",
109    "moment": "2.29.1",
110    "moment-timezone": "^0.5.32",
111    "nouislider-react": "^3.3.9",
112    "npm": "^7.6.3",
113    "prop-types": "^15.7.2",
114    "query-string": "^6.14.0",
115    "react": "^16.13.1",
116    "react-apexcharts": "^1.3.7",
117    "react-auth-code-input": "^1.0.0",
118    "react-avatar": "^3.10.0",
119    "react-bootstrap": "^1.5.0",
120    "react-bootstrap-editable": "^0.8.2",
121    "react-bootstrap-sweetalert": "^5.2.0",
122    "react-bootstrap-table-next": "^4.0.3",
123    "react-bootstrap-table2-editor": "^1.4.0",
124    "react-bootstrap-table2-paginator": "^2.1.2",
125    "react-bootstrap-table2-toolkit": "^2.1.3",
126    "react-chartist": "^0.14.3",
127    "react-chartjs-2": "^2.11.1",
128    "react-color": "^2.19.3",
129    "react-confirm-alert": "^2.7.0",
130    "react-content-loader": "^6.0.1",
131    "react-countdown": "^2.3.1",
132    "react-countup": "^4.3.3",
133    "react-cropper": "^2.1.4",
134    "react-data-table-component": "^6.11.8",
135    "react-date-picker": "^8.0.6",
136    "react-datepicker": "^3.4.1",
137    "react-dom": "^16.13.1",
138    "react-draft-wysiwyg": "^1.14.5",
139    "react-drag-listview": "^0.1.8",
140    "react-drawer": "^1.3.4",
141    "react-dropzone": "^11.2.4",
142    "react-dual-listbox": "^2.0.0",
143    "react-facebook-login": "^4.1.1",
144    "react-flatpickr": "^3.10.6",
145    "react-google-login": "^5.2.2",
146    "react-hook-form": "^7.15.2",
147    "react-i18next": "^11.8.5",
148    "react-icons": "^4.2.0",
149    "react-image-lightbox": "^5.1.1",
150    "react-input-mask": "^2.0.4",
151    "react-jvectormap": "^0.0.16",
152    "react-leaflet": "^3.0.5",
153    "react-meta-tags": "^1.0.1",
154    "react-modal-video": "^1.2.6",
155    "react-notifications": "^1.7.2",
156    "react-number-format": "^4.7.3",
157    "react-perfect-scrollbar": "^1.5.8",
158    "react-rangeslider": "^2.2.0",
159    "react-rating": "^2.0.5",
160    "react-rating-tooltip": "^1.1.6",
161    "react-redux": "^7.2.1",
162    "react-responsive-carousel": "^3.2.11",
163    "react-router-dom": "^5.2.0",
164    "react-script": "^2.0.5",
165    "react-scripts": "3.4.3",
166    "react-select": "^4.3.1",
167    "react-sparklines": "^1.7.0",
168    "react-star-ratings": "^2.3.0",
169    "react-super-responsive-table": "^5.2.0",
170    "react-switch": "^6.0.0",
171    "react-table": "^7.6.3",
172    "react-toastify": "^7.0.3",
173    "react-toastr": "^3.0.0",
174    "react-twitter-auth": "0.0.13",
175    "reactstrap": "^8.8.1",
176    "recharts": "^2.0.8",
177    "redux": "^4.0.5",
178    "redux-saga": "^1.1.3",
179    "reselect": "^4.0.0",
180    "sass": "^1.37.5",
181    "simplebar-react": "^2.3.0",
182    "styled": "^1.0.0",
183    "styled-components": "^5.2.1",
184    "toastr": "^2.1.4",
185    "typescript": "^4.0.2",
186    "universal-cookie": "^4.0.4"
187  },
188  "devDependencies": {
189    "@typescript-eslint/eslint-plugin": "^2.27.0",
190    "@typescript-eslint/parser": "^2.27.0",
191    "@typescript-eslint/typescript-estree": "^4.15.2",
192    "eslint-config-prettier": "^6.10.1",
193    "eslint-plugin-prettier": "^3.1.2",
194    "husky": "^4.2.5",
195    "lint-staged": "^10.1.3",
196    "prettier": "^1.19.1",
197    "react-test-renderer": "^16.13.1",
198    "redux-devtools-extension": "^2.13.8",
199    "redux-mock-store": "^1.5.4"
200  },
201  "scripts": {
202    "start": "react-scripts start",
203    "build": "react-scripts build && mv build ./deploy/build",
204    "build-local": "react-scripts build",
205    "test": "react-scripts test",
206    "eject": "react-scripts eject"
207  },
208  "eslintConfig": {
209    "extends": "react-app"
210  },
211  "husky": {
212    "hooks": {
213      "pre-commit": "lint-staged"
214    }
215  },
216  "lint-staged": {
217    "*.{js,ts,tsx}": [
218      "eslint --fix"
219    ]
220  },
221  "browserslist": {
222    "production": [
223      ">0.2%",
224      "not dead",
225      "not op_mini all"
226    ],
227    "development": [
228      "last 1 chrome version",
229      "last 1 firefox version",
230      "last 1 safari version"
231    ]
232  }
233}
234

ANSWER

Answered 2022-Mar-16 at 07:01

First, this error message is indeed expected on Jan. 11th, 2022.
See "Improving Git protocol security on GitHub".

January 11, 2022 Final brownout.

This is the full brownout period where we’ll temporarily stop accepting the deprecated key and signature types, ciphers, and MACs, and the unencrypted Git protocol.
This will help clients discover any lingering use of older keys or old URLs.

Second, check your package.json dependencies for any git:// URL, as in this example, fixed in this PR.

As noted by Jörg W Mittag:

There was a 4-month warning.
The entire Internet has been moving away from unauthenticated, unencrypted protocols for a decade, it's not like this is a huge surprise.

Personally, I consider it less an "issue" and more "detecting unmaintained dependencies".

Plus, this is still only the brownout period, so the protocol will only be disabled for a short period of time, allowing developers to discover the problem.

The permanent shutdown is not until March 15th.


For GitHub Actions:

As in actions/checkout issue 14, you can add as a first step:

1Command: git
2Arguments: ls-remote --tags --heads git://github.com/adobe-webplatform/eve.git
3Directory: /home/runner/work/stackstream-fe/stackstream-fe
4Output:
5fatal: remote error: 
6  The unauthenticated git protocol on port 9418 is no longer supported.
7    - name: Installing modules
8      run: yarn install
9  steps:
10  - name: Checkout
11    uses: actions/checkout@v2
12
13  - id: vars
14    run: |
15      if [ '${{ github.ref }}' == 'refs/heads/master' ]; then echo "::set-output name=environment::prod_stackstream" ; echo "::set-output name=api-url::api" ; elif [ '${{ github.ref }}' == 'refs/heads/staging' ]; then echo "::set-output name=environment::staging_stackstream"  ; echo "::set-output name=api-url::stagingapi" ; else echo "::set-output name=environment::dev_stackstream" ; echo "::set-output name=api-url::devapi" ; fi
16
17  - uses: pCYSl5EDgo/cat@master
18    id: slack
19    with:
20      path: .github/workflows/slack.txt
21
22  - name: Slack Start Notification
23    uses: 8398a7/action-slack@v3
24    env:
25      SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
26      ENVIRONMENT: '`${{ steps.vars.outputs.environment }}`'
27      COLOR: good
28      STATUS: '`Started`'
29    with:
30      status: custom
31      fields: workflow,job,commit,repo,ref,author,took
32      custom_payload: |
33        ${{ steps.slack.outputs.text }}
34
35  - name: Installing modules
36    env:
37      REACT_APP_API_URL: 'https://${{ steps.vars.outputs.api-url }}mergestack.com/api/v1'
38    run: yarn install
39
40  - name: Create Frontend Build
41    env:
42      REACT_APP_API_URL: 'https://${{ steps.vars.outputs.api-url }}mergestack.com/api/v1'
43    run: yarn build
44
45  - name: Deploy to Frontend Server DEV
46    if: ${{ contains(github.ref, 'dev') }}
47    uses: easingthemes/ssh-deploy@v2.1.5
48    env:
49      SSH_PRIVATE_KEY: ${{ secrets.DEV_KEY }}
50      ARGS: '-rltgoDzvO --delete'
51      SOURCE: 'deploy/'
52      REMOTE_HOST: ${{ secrets.DEV_HOST }}
53      REMOTE_USER: plyfolio-dev
54      TARGET: '/home/plyfolio-dev/${{ steps.vars.outputs.environment }}/fe/deploy'
55   {
56  "name": "stackstream-fe",
57  "version": "1.0.0",
58  "authors": [
59    "fayyaznofal@gmail.com"
60  ],
61  "private": true,
62  "dependencies": {
63    "@fortawesome/fontawesome-svg-core": "^1.2.34",
64    "@fortawesome/free-solid-svg-icons": "^5.15.2",
65    "@fortawesome/react-fontawesome": "^0.1.14",
66    "@fullcalendar/bootstrap": "^5.5.0",
67    "@fullcalendar/core": "^5.5.0",
68    "@fullcalendar/daygrid": "^5.5.0",
69    "@fullcalendar/interaction": "^5.5.0",
70    "@fullcalendar/react": "^5.5.0",
71    "@lourenci/react-kanban": "^2.1.0",
72    "@redux-saga/simple-saga-monitor": "^1.1.2",
73    "@testing-library/jest-dom": "^5.11.9",
74    "@testing-library/react": "^11.2.3",
75    "@testing-library/user-event": "^12.6.0",
76    "@toast-ui/react-chart": "^1.0.2",
77    "@types/jest": "^26.0.14",
78    "@types/node": "^14.10.3",
79    "@types/react": "^16.9.49",
80    "@types/react-dom": "^16.9.8",
81    "@vtaits/react-color-picker": "^0.1.1",
82    "apexcharts": "^3.23.1",
83    "availity-reactstrap-validation": "^2.7.0",
84    "axios": "^0.21.1",
85    "axios-mock-adapter": "^1.19.0",
86    "axios-progress-bar": "^1.2.0",
87    "bootstrap": "^5.0.0-beta2",
88    "chart.js": "^2.9.4",
89    "chartist": "^0.11.4",
90    "classnames": "^2.2.6",
91    "components": "^0.1.0",
92    "dotenv": "^8.2.0",
93    "draft-js": "^0.11.7",
94    "echarts": "^4.9.0",
95    "echarts-for-react": "^2.0.16",
96    "firebase": "^8.2.3",
97    "google-maps-react": "^2.0.6",
98    "history": "^4.10.1",
99    "i": "^0.3.6",
100    "i18next": "^19.8.4",
101    "i18next-browser-languagedetector": "^6.0.1",
102    "jsonwebtoken": "^8.5.1",
103    "leaflet": "^1.7.1",
104    "lodash": "^4.17.21",
105    "lodash.clonedeep": "^4.5.0",
106    "lodash.get": "^4.4.2",
107    "metismenujs": "^1.2.1",
108    "mkdirp": "^1.0.4",
109    "moment": "2.29.1",
110    "moment-timezone": "^0.5.32",
111    "nouislider-react": "^3.3.9",
112    "npm": "^7.6.3",
113    "prop-types": "^15.7.2",
114    "query-string": "^6.14.0",
115    "react": "^16.13.1",
116    "react-apexcharts": "^1.3.7",
117    "react-auth-code-input": "^1.0.0",
118    "react-avatar": "^3.10.0",
119    "react-bootstrap": "^1.5.0",
120    "react-bootstrap-editable": "^0.8.2",
121    "react-bootstrap-sweetalert": "^5.2.0",
122    "react-bootstrap-table-next": "^4.0.3",
123    "react-bootstrap-table2-editor": "^1.4.0",
124    "react-bootstrap-table2-paginator": "^2.1.2",
125    "react-bootstrap-table2-toolkit": "^2.1.3",
126    "react-chartist": "^0.14.3",
127    "react-chartjs-2": "^2.11.1",
128    "react-color": "^2.19.3",
129    "react-confirm-alert": "^2.7.0",
130    "react-content-loader": "^6.0.1",
131    "react-countdown": "^2.3.1",
132    "react-countup": "^4.3.3",
133    "react-cropper": "^2.1.4",
134    "react-data-table-component": "^6.11.8",
135    "react-date-picker": "^8.0.6",
136    "react-datepicker": "^3.4.1",
137    "react-dom": "^16.13.1",
138    "react-draft-wysiwyg": "^1.14.5",
139    "react-drag-listview": "^0.1.8",
140    "react-drawer": "^1.3.4",
141    "react-dropzone": "^11.2.4",
142    "react-dual-listbox": "^2.0.0",
143    "react-facebook-login": "^4.1.1",
144    "react-flatpickr": "^3.10.6",
145    "react-google-login": "^5.2.2",
146    "react-hook-form": "^7.15.2",
147    "react-i18next": "^11.8.5",
148    "react-icons": "^4.2.0",
149    "react-image-lightbox": "^5.1.1",
150    "react-input-mask": "^2.0.4",
151    "react-jvectormap": "^0.0.16",
152    "react-leaflet": "^3.0.5",
153    "react-meta-tags": "^1.0.1",
154    "react-modal-video": "^1.2.6",
155    "react-notifications": "^1.7.2",
156    "react-number-format": "^4.7.3",
157    "react-perfect-scrollbar": "^1.5.8",
158    "react-rangeslider": "^2.2.0",
159    "react-rating": "^2.0.5",
160    "react-rating-tooltip": "^1.1.6",
161    "react-redux": "^7.2.1",
162    "react-responsive-carousel": "^3.2.11",
163    "react-router-dom": "^5.2.0",
164    "react-script": "^2.0.5",
165    "react-scripts": "3.4.3",
166    "react-select": "^4.3.1",
167    "react-sparklines": "^1.7.0",
168    "react-star-ratings": "^2.3.0",
169    "react-super-responsive-table": "^5.2.0",
170    "react-switch": "^6.0.0",
171    "react-table": "^7.6.3",
172    "react-toastify": "^7.0.3",
173    "react-toastr": "^3.0.0",
174    "react-twitter-auth": "0.0.13",
175    "reactstrap": "^8.8.1",
176    "recharts": "^2.0.8",
177    "redux": "^4.0.5",
178    "redux-saga": "^1.1.3",
179    "reselect": "^4.0.0",
180    "sass": "^1.37.5",
181    "simplebar-react": "^2.3.0",
182    "styled": "^1.0.0",
183    "styled-components": "^5.2.1",
184    "toastr": "^2.1.4",
185    "typescript": "^4.0.2",
186    "universal-cookie": "^4.0.4"
187  },
188  "devDependencies": {
189    "@typescript-eslint/eslint-plugin": "^2.27.0",
190    "@typescript-eslint/parser": "^2.27.0",
191    "@typescript-eslint/typescript-estree": "^4.15.2",
192    "eslint-config-prettier": "^6.10.1",
193    "eslint-plugin-prettier": "^3.1.2",
194    "husky": "^4.2.5",
195    "lint-staged": "^10.1.3",
196    "prettier": "^1.19.1",
197    "react-test-renderer": "^16.13.1",
198    "redux-devtools-extension": "^2.13.8",
199    "redux-mock-store": "^1.5.4"
200  },
201  "scripts": {
202    "start": "react-scripts start",
203    "build": "react-scripts build && mv build ./deploy/build",
204    "build-local": "react-scripts build",
205    "test": "react-scripts test",
206    "eject": "react-scripts eject"
207  },
208  "eslintConfig": {
209    "extends": "react-app"
210  },
211  "husky": {
212    "hooks": {
213      "pre-commit": "lint-staged"
214    }
215  },
216  "lint-staged": {
217    "*.{js,ts,tsx}": [
218      "eslint --fix"
219    ]
220  },
221  "browserslist": {
222    "production": [
223      ">0.2%",
224      "not dead",
225      "not op_mini all"
226    ],
227    "development": [
228      "last 1 chrome version",
229      "last 1 firefox version",
230      "last 1 safari version"
231    ]
232  }
233}
234    - name: Fix up git URLs
235      run: echo -e '[url "https://github.com/"]\n  insteadOf = "git://github.com/"' >> ~/.gitconfig
236

That will change any git://github.com/ into https://github.com/.

For local projects

For all your repositories, you can set:

1Command: git
2Arguments: ls-remote --tags --heads git://github.com/adobe-webplatform/eve.git
3Directory: /home/runner/work/stackstream-fe/stackstream-fe
4Output:
5fatal: remote error: 
6  The unauthenticated git protocol on port 9418 is no longer supported.
7    - name: Installing modules
8      run: yarn install
9  steps:
10  - name: Checkout
11    uses: actions/checkout@v2
12
13  - id: vars
14    run: |
15      if [ '${{ github.ref }}' == 'refs/heads/master' ]; then echo "::set-output name=environment::prod_stackstream" ; echo "::set-output name=api-url::api" ; elif [ '${{ github.ref }}' == 'refs/heads/staging' ]; then echo "::set-output name=environment::staging_stackstream"  ; echo "::set-output name=api-url::stagingapi" ; else echo "::set-output name=environment::dev_stackstream" ; echo "::set-output name=api-url::devapi" ; fi
16
17  - uses: pCYSl5EDgo/cat@master
18    id: slack
19    with:
20      path: .github/workflows/slack.txt
21
22  - name: Slack Start Notification
23    uses: 8398a7/action-slack@v3
24    env:
25      SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
26      ENVIRONMENT: '`${{ steps.vars.outputs.environment }}`'
27      COLOR: good
28      STATUS: '`Started`'
29    with:
30      status: custom
31      fields: workflow,job,commit,repo,ref,author,took
32      custom_payload: |
33        ${{ steps.slack.outputs.text }}
34
35  - name: Installing modules
36    env:
37      REACT_APP_API_URL: 'https://${{ steps.vars.outputs.api-url }}mergestack.com/api/v1'
38    run: yarn install
39
40  - name: Create Frontend Build
41    env:
42      REACT_APP_API_URL: 'https://${{ steps.vars.outputs.api-url }}mergestack.com/api/v1'
43    run: yarn build
44
45  - name: Deploy to Frontend Server DEV
46    if: ${{ contains(github.ref, 'dev') }}
47    uses: easingthemes/ssh-deploy@v2.1.5
48    env:
49      SSH_PRIVATE_KEY: ${{ secrets.DEV_KEY }}
50      ARGS: '-rltgoDzvO --delete'
51      SOURCE: 'deploy/'
52      REMOTE_HOST: ${{ secrets.DEV_HOST }}
53      REMOTE_USER: plyfolio-dev
54      TARGET: '/home/plyfolio-dev/${{ steps.vars.outputs.environment }}/fe/deploy'
55   {
56  "name": "stackstream-fe",
57  "version": "1.0.0",
58  "authors": [
59    "fayyaznofal@gmail.com"
60  ],
61  "private": true,
62  "dependencies": {
63    "@fortawesome/fontawesome-svg-core": "^1.2.34",
64    "@fortawesome/free-solid-svg-icons": "^5.15.2",
65    "@fortawesome/react-fontawesome": "^0.1.14",
66    "@fullcalendar/bootstrap": "^5.5.0",
67    "@fullcalendar/core": "^5.5.0",
68    "@fullcalendar/daygrid": "^5.5.0",
69    "@fullcalendar/interaction": "^5.5.0",
70    "@fullcalendar/react": "^5.5.0",
71    "@lourenci/react-kanban": "^2.1.0",
72    "@redux-saga/simple-saga-monitor": "^1.1.2",
73    "@testing-library/jest-dom": "^5.11.9",
74    "@testing-library/react": "^11.2.3",
75    "@testing-library/user-event": "^12.6.0",
76    "@toast-ui/react-chart": "^1.0.2",
77    "@types/jest": "^26.0.14",
78    "@types/node": "^14.10.3",
79    "@types/react": "^16.9.49",
80    "@types/react-dom": "^16.9.8",
81    "@vtaits/react-color-picker": "^0.1.1",
82    "apexcharts": "^3.23.1",
83    "availity-reactstrap-validation": "^2.7.0",
84    "axios": "^0.21.1",
85    "axios-mock-adapter": "^1.19.0",
86    "axios-progress-bar": "^1.2.0",
87    "bootstrap": "^5.0.0-beta2",
88    "chart.js": "^2.9.4",
89    "chartist": "^0.11.4",
90    "classnames": "^2.2.6",
91    "components": "^0.1.0",
92    "dotenv": "^8.2.0",
93    "draft-js": "^0.11.7",
94    "echarts": "^4.9.0",
95    "echarts-for-react": "^2.0.16",
96    "firebase": "^8.2.3",
97    "google-maps-react": "^2.0.6",
98    "history": "^4.10.1",
99    "i": "^0.3.6",
100    "i18next": "^19.8.4",
101    "i18next-browser-languagedetector": "^6.0.1",
102    "jsonwebtoken": "^8.5.1",
103    "leaflet": "^1.7.1",
104    "lodash": "^4.17.21",
105    "lodash.clonedeep": "^4.5.0",
106    "lodash.get": "^4.4.2",
107    "metismenujs": "^1.2.1",
108    "mkdirp": "^1.0.4",
109    "moment": "2.29.1",
110    "moment-timezone": "^0.5.32",
111    "nouislider-react": "^3.3.9",
112    "npm": "^7.6.3",
113    "prop-types": "^15.7.2",
114    "query-string": "^6.14.0",
115    "react": "^16.13.1",
116    "react-apexcharts": "^1.3.7",
117    "react-auth-code-input": "^1.0.0",
118    "react-avatar": "^3.10.0",
119    "react-bootstrap": "^1.5.0",
120    "react-bootstrap-editable": "^0.8.2",
121    "react-bootstrap-sweetalert": "^5.2.0",
122    "react-bootstrap-table-next": "^4.0.3",
123    "react-bootstrap-table2-editor": "^1.4.0",
124    "react-bootstrap-table2-paginator": "^2.1.2",
125    "react-bootstrap-table2-toolkit": "^2.1.3",
126    "react-chartist": "^0.14.3",
127    "react-chartjs-2": "^2.11.1",
128    "react-color": "^2.19.3",
129    "react-confirm-alert": "^2.7.0",
130    "react-content-loader": "^6.0.1",
131    "react-countdown": "^2.3.1",
132    "react-countup": "^4.3.3",
133    "react-cropper": "^2.1.4",
134    "react-data-table-component": "^6.11.8",
135    "react-date-picker": "^8.0.6",
136    "react-datepicker": "^3.4.1",
137    "react-dom": "^16.13.1",
138    "react-draft-wysiwyg": "^1.14.5",
139    "react-drag-listview": "^0.1.8",
140    "react-drawer": "^1.3.4",
141    "react-dropzone": "^11.2.4",
142    "react-dual-listbox": "^2.0.0",
143    "react-facebook-login": "^4.1.1",
144    "react-flatpickr": "^3.10.6",
145    "react-google-login": "^5.2.2",
146    "react-hook-form": "^7.15.2",
147    "react-i18next": "^11.8.5",
148    "react-icons": "^4.2.0",
149    "react-image-lightbox": "^5.1.1",
150    "react-input-mask": "^2.0.4",
151    "react-jvectormap": "^0.0.16",
152    "react-leaflet": "^3.0.5",
153    "react-meta-tags": "^1.0.1",
154    "react-modal-video": "^1.2.6",
155    "react-notifications": "^1.7.2",
156    "react-number-format": "^4.7.3",
157    "react-perfect-scrollbar": "^1.5.8",
158    "react-rangeslider": "^2.2.0",
159    "react-rating": "^2.0.5",
160    "react-rating-tooltip": "^1.1.6",
161    "react-redux": "^7.2.1",
162    "react-responsive-carousel": "^3.2.11",
163    "react-router-dom": "^5.2.0",
164    "react-script": "^2.0.5",
165    "react-scripts": "3.4.3",
166    "react-select": "^4.3.1",
167    "react-sparklines": "^1.7.0",
168    "react-star-ratings": "^2.3.0",
169    "react-super-responsive-table": "^5.2.0",
170    "react-switch": "^6.0.0",
171    "react-table": "^7.6.3",
172    "react-toastify": "^7.0.3",
173    "react-toastr": "^3.0.0",
174    "react-twitter-auth": "0.0.13",
175    "reactstrap": "^8.8.1",
176    "recharts": "^2.0.8",
177    "redux": "^4.0.5",
178    "redux-saga": "^1.1.3",
179    "reselect": "^4.0.0",
180    "sass": "^1.37.5",
181    "simplebar-react": "^2.3.0",
182    "styled": "^1.0.0",
183    "styled-components": "^5.2.1",
184    "toastr": "^2.1.4",
185    "typescript": "^4.0.2",
186    "universal-cookie": "^4.0.4"
187  },
188  "devDependencies": {
189    "@typescript-eslint/eslint-plugin": "^2.27.0",
190    "@typescript-eslint/parser": "^2.27.0",
191    "@typescript-eslint/typescript-estree": "^4.15.2",
192    "eslint-config-prettier": "^6.10.1",
193    "eslint-plugin-prettier": "^3.1.2",
194    "husky": "^4.2.5",
195    "lint-staged": "^10.1.3",
196    "prettier": "^1.19.1",
197    "react-test-renderer": "^16.13.1",
198    "redux-devtools-extension": "^2.13.8",
199    "redux-mock-store": "^1.5.4"
200  },
201  "scripts": {
202    "start": "react-scripts start",
203    "build": "react-scripts build && mv build ./deploy/build",
204    "build-local": "react-scripts build",
205    "test": "react-scripts test",
206    "eject": "react-scripts eject"
207  },
208  "eslintConfig": {
209    "extends": "react-app"
210  },
211  "husky": {
212    "hooks": {
213      "pre-commit": "lint-staged"
214    }
215  },
216  "lint-staged": {
217    "*.{js,ts,tsx}": [
218      "eslint --fix"
219    ]
220  },
221  "browserslist": {
222    "production": [
223      ">0.2%",
224      "not dead",
225      "not op_mini all"
226    ],
227    "development": [
228      "last 1 chrome version",
229      "last 1 firefox version",
230      "last 1 safari version"
231    ]
232  }
233}
234    - name: Fix up git URLs
235      run: echo -e '[url "https://github.com/"]\n  insteadOf = "git://github.com/"' >> ~/.gitconfig
236git config --global url."https://github.com/".insteadOf git://github.com/
237

You can also use SSH, but GitHub Security reminds us that, as of March 15th, 2022, GitHub stopped accepting DSA keys. RSA keys uploaded after Nov 2, 2021 will work only with SHA-2 signatures.
The deprecated MACs, ciphers, and unencrypted Git protocol are permanently disabled.

So this (with the right key) would work:

1Command: git
2Arguments: ls-remote --tags --heads git://github.com/adobe-webplatform/eve.git
3Directory: /home/runner/work/stackstream-fe/stackstream-fe
4Output:
5fatal: remote error: 
6  The unauthenticated git protocol on port 9418 is no longer supported.
7    - name: Installing modules
8      run: yarn install
9  steps:
10  - name: Checkout
11    uses: actions/checkout@v2
12
13  - id: vars
14    run: |
15      if [ '${{ github.ref }}' == 'refs/heads/master' ]; then echo "::set-output name=environment::prod_stackstream" ; echo "::set-output name=api-url::api" ; elif [ '${{ github.ref }}' == 'refs/heads/staging' ]; then echo "::set-output name=environment::staging_stackstream"  ; echo "::set-output name=api-url::stagingapi" ; else echo "::set-output name=environment::dev_stackstream" ; echo "::set-output name=api-url::devapi" ; fi
16
17  - uses: pCYSl5EDgo/cat@master
18    id: slack
19    with:
20      path: .github/workflows/slack.txt
21
22  - name: Slack Start Notification
23    uses: 8398a7/action-slack@v3
24    env:
25      SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
26      ENVIRONMENT: '`${{ steps.vars.outputs.environment }}`'
27      COLOR: good
28      STATUS: '`Started`'
29    with:
30      status: custom
31      fields: workflow,job,commit,repo,ref,author,took
32      custom_payload: |
33        ${{ steps.slack.outputs.text }}
34
35  - name: Installing modules
36    env:
37      REACT_APP_API_URL: 'https://${{ steps.vars.outputs.api-url }}mergestack.com/api/v1'
38    run: yarn install
39
40  - name: Create Frontend Build
41    env:
42      REACT_APP_API_URL: 'https://${{ steps.vars.outputs.api-url }}mergestack.com/api/v1'
43    run: yarn build
44
45  - name: Deploy to Frontend Server DEV
46    if: ${{ contains(github.ref, 'dev') }}
47    uses: easingthemes/ssh-deploy@v2.1.5
48    env:
49      SSH_PRIVATE_KEY: ${{ secrets.DEV_KEY }}
50      ARGS: '-rltgoDzvO --delete'
51      SOURCE: 'deploy/'
52      REMOTE_HOST: ${{ secrets.DEV_HOST }}
53      REMOTE_USER: plyfolio-dev
54      TARGET: '/home/plyfolio-dev/${{ steps.vars.outputs.environment }}/fe/deploy'
55   {
56  "name": "stackstream-fe",
57  "version": "1.0.0",
58  "authors": [
59    "fayyaznofal@gmail.com"
60  ],
61  "private": true,
62  "dependencies": {
63    "@fortawesome/fontawesome-svg-core": "^1.2.34",
64    "@fortawesome/free-solid-svg-icons": "^5.15.2",
65    "@fortawesome/react-fontawesome": "^0.1.14",
66    "@fullcalendar/bootstrap": "^5.5.0",
67    "@fullcalendar/core": "^5.5.0",
68    "@fullcalendar/daygrid": "^5.5.0",
69    "@fullcalendar/interaction": "^5.5.0",
70    "@fullcalendar/react": "^5.5.0",
71    "@lourenci/react-kanban": "^2.1.0",
72    "@redux-saga/simple-saga-monitor": "^1.1.2",
73    "@testing-library/jest-dom": "^5.11.9",
74    "@testing-library/react": "^11.2.3",
75    "@testing-library/user-event": "^12.6.0",
76    "@toast-ui/react-chart": "^1.0.2",
77    "@types/jest": "^26.0.14",
78    "@types/node": "^14.10.3",
79    "@types/react": "^16.9.49",
80    "@types/react-dom": "^16.9.8",
81    "@vtaits/react-color-picker": "^0.1.1",
82    "apexcharts": "^3.23.1",
83    "availity-reactstrap-validation": "^2.7.0",
84    "axios": "^0.21.1",
85    "axios-mock-adapter": "^1.19.0",
86    "axios-progress-bar": "^1.2.0",
87    "bootstrap": "^5.0.0-beta2",
88    "chart.js": "^2.9.4",
89    "chartist": "^0.11.4",
90    "classnames": "^2.2.6",
91    "components": "^0.1.0",
92    "dotenv": "^8.2.0",
93    "draft-js": "^0.11.7",
94    "echarts": "^4.9.0",
95    "echarts-for-react": "^2.0.16",
96    "firebase": "^8.2.3",
97    "google-maps-react": "^2.0.6",
98    "history": "^4.10.1",
99    "i": "^0.3.6",
100    "i18next": "^19.8.4",
101    "i18next-browser-languagedetector": "^6.0.1",
102    "jsonwebtoken": "^8.5.1",
103    "leaflet": "^1.7.1",
104    "lodash": "^4.17.21",
105    "lodash.clonedeep": "^4.5.0",
106    "lodash.get": "^4.4.2",
107    "metismenujs": "^1.2.1",
108    "mkdirp": "^1.0.4",
109    "moment": "2.29.1",
110    "moment-timezone": "^0.5.32",
111    "nouislider-react": "^3.3.9",
112    "npm": "^7.6.3",
113    "prop-types": "^15.7.2",
114    "query-string": "^6.14.0",
115    "react": "^16.13.1",
116    "react-apexcharts": "^1.3.7",
117    "react-auth-code-input": "^1.0.0",
118    "react-avatar": "^3.10.0",
119    "react-bootstrap": "^1.5.0",
120    "react-bootstrap-editable": "^0.8.2",
121    "react-bootstrap-sweetalert": "^5.2.0",
122    "react-bootstrap-table-next": "^4.0.3",
123    "react-bootstrap-table2-editor": "^1.4.0",
124    "react-bootstrap-table2-paginator": "^2.1.2",
125    "react-bootstrap-table2-toolkit": "^2.1.3",
126    "react-chartist": "^0.14.3",
127    "react-chartjs-2": "^2.11.1",
128    "react-color": "^2.19.3",
129    "react-confirm-alert": "^2.7.0",
130    "react-content-loader": "^6.0.1",
131    "react-countdown": "^2.3.1",
132    "react-countup": "^4.3.3",
133    "react-cropper": "^2.1.4",
134    "react-data-table-component": "^6.11.8",
135    "react-date-picker": "^8.0.6",
136    "react-datepicker": "^3.4.1",
137    "react-dom": "^16.13.1",
138    "react-draft-wysiwyg": "^1.14.5",
139    "react-drag-listview": "^0.1.8",
140    "react-drawer": "^1.3.4",
141    "react-dropzone": "^11.2.4",
142    "react-dual-listbox": "^2.0.0",
143    "react-facebook-login": "^4.1.1",
144    "react-flatpickr": "^3.10.6",
145    "react-google-login": "^5.2.2",
146    "react-hook-form": "^7.15.2",
147    "react-i18next": "^11.8.5",
148    "react-icons": "^4.2.0",
149    "react-image-lightbox": "^5.1.1",
150    "react-input-mask": "^2.0.4",
151    "react-jvectormap": "^0.0.16",
152    "react-leaflet": "^3.0.5",
153    "react-meta-tags": "^1.0.1",
154    "react-modal-video": "^1.2.6",
155    "react-notifications": "^1.7.2",
156    "react-number-format": "^4.7.3",
157    "react-perfect-scrollbar": "^1.5.8",
158    "react-rangeslider": "^2.2.0",
159    "react-rating": "^2.0.5",
160    "react-rating-tooltip": "^1.1.6",
161    "react-redux": "^7.2.1",
162    "react-responsive-carousel": "^3.2.11",
163    "react-router-dom": "^5.2.0",
164    "react-script": "^2.0.5",
165    "react-scripts": "3.4.3",
166    "react-select": "^4.3.1",
167    "react-sparklines": "^1.7.0",
168    "react-star-ratings": "^2.3.0",
169    "react-super-responsive-table": "^5.2.0",
170    "react-switch": "^6.0.0",
171    "react-table": "^7.6.3",
172    "react-toastify": "^7.0.3",
173    "react-toastr": "^3.0.0",
174    "react-twitter-auth": "0.0.13",
175    "reactstrap": "^8.8.1",
176    "recharts": "^2.0.8",
177    "redux": "^4.0.5",
178    "redux-saga": "^1.1.3",
179    "reselect": "^4.0.0",
180    "sass": "^1.37.5",
181    "simplebar-react": "^2.3.0",
182    "styled": "^1.0.0",
183    "styled-components": "^5.2.1",
184    "toastr": "^2.1.4",
185    "typescript": "^4.0.2",
186    "universal-cookie": "^4.0.4"
187  },
188  "devDependencies": {
189    "@typescript-eslint/eslint-plugin": "^2.27.0",
190    "@typescript-eslint/parser": "^2.27.0",
191    "@typescript-eslint/typescript-estree": "^4.15.2",
192    "eslint-config-prettier": "^6.10.1",
193    "eslint-plugin-prettier": "^3.1.2",
194    "husky": "^4.2.5",
195    "lint-staged": "^10.1.3",
196    "prettier": "^1.19.1",
197    "react-test-renderer": "^16.13.1",
198    "redux-devtools-extension": "^2.13.8",
199    "redux-mock-store": "^1.5.4"
200  },
201  "scripts": {
202    "start": "react-scripts start",
203    "build": "react-scripts build && mv build ./deploy/build",
204    "build-local": "react-scripts build",
205    "test": "react-scripts test",
206    "eject": "react-scripts eject"
207  },
208  "eslintConfig": {
209    "extends": "react-app"
210  },
211  "husky": {
212    "hooks": {
213      "pre-commit": "lint-staged"
214    }
215  },
216  "lint-staged": {
217    "*.{js,ts,tsx}": [
218      "eslint --fix"
219    ]
220  },
221  "browserslist": {
222    "production": [
223      ">0.2%",
224      "not dead",
225      "not op_mini all"
226    ],
227    "development": [
228      "last 1 chrome version",
229      "last 1 firefox version",
230      "last 1 safari version"
231    ]
232  }
233}
234    - name: Fix up git URLs
235      run: echo -e '[url "https://github.com/"]\n  insteadOf = "git://github.com/"' >> ~/.gitconfig
236git config --global url."https://github.com/".insteadOf git://github.com/
237git config --global url."git@github.com:".insteadOf git://github.com/
238

That will change any git://github.com/ (unencrypted Git protocol) into git@github.com: (SSH URL).

Source https://stackoverflow.com/questions/70663523

QUESTION

How to change the date picker from spinner to calendar dialogue in Android Kotlin

Asked 2022-Mar-16 at 10:31

How to change my spinner date picker to normal calendar with an option to keyboard entry as shown in the attached picture

Here is the code.

1 private val datePickerDialog by lazy {
2            DatePickerDialog(requireActivity(), R.style.SpinnerDatePickerDialog).apply {
3                setTitle(R.string.select_date)
4                datePicker.maxDate = LocalDate.now().minusDays(1).toMillis()
5                setOnDateSetListener { _, year, month, dayOfMonth ->
6                    viewModel.onDateSelected(year, month, dayOfMonth)
7                }
8            }
9        }
10

enter image description here

ANSWER

Answered 2022-Mar-16 at 10:31

Follow the below code to achieve a material calendar view.

(1) Add the below dependency in your app Gradle.

implementation 'com.google.android.material:material:1.5.0'

(2) Use the below style for your activity.

1 private val datePickerDialog by lazy {
2            DatePickerDialog(requireActivity(), R.style.SpinnerDatePickerDialog).apply {
3                setTitle(R.string.select_date)
4                datePicker.maxDate = LocalDate.now().minusDays(1).toMillis()
5                setOnDateSetListener { _, year, month, dayOfMonth ->
6                    viewModel.onDateSelected(year, month, dayOfMonth)
7                }
8            }
9        }
10    <!-- Base application theme. -->
11<style name="ScreenTheme" parent="Theme.MaterialComponents.Light.NoActionBar.Bridge">
12    <!-- Customize your theme here. -->
13    <item name="colorPrimary">@color/colorPrimary</item>
14    <item name="colorPrimaryDark">@color/colorPrimary</item>
15    <item name="colorAccent">@color/colorAccent</item>
16
17    <item name="materialCalendarStyle">@style/Widget.MaterialComponents.MaterialCalendar</item>
18    <item name="materialCalendarFullscreenTheme">@style/ThemeOverlay.MaterialComponents.MaterialCalendar.Fullscreen</item>
19    <item name="materialCalendarTheme">@style/ThemeOverlay.MaterialComponents.MaterialCalendar</item>
20</style>
21

(3) Set above style in Manifest.xml file with activity.

1 private val datePickerDialog by lazy {
2            DatePickerDialog(requireActivity(), R.style.SpinnerDatePickerDialog).apply {
3                setTitle(R.string.select_date)
4                datePicker.maxDate = LocalDate.now().minusDays(1).toMillis()
5                setOnDateSetListener { _, year, month, dayOfMonth ->
6                    viewModel.onDateSelected(year, month, dayOfMonth)
7                }
8            }
9        }
10    <!-- Base application theme. -->
11<style name="ScreenTheme" parent="Theme.MaterialComponents.Light.NoActionBar.Bridge">
12    <!-- Customize your theme here. -->
13    <item name="colorPrimary">@color/colorPrimary</item>
14    <item name="colorPrimaryDark">@color/colorPrimary</item>
15    <item name="colorAccent">@color/colorAccent</item>
16
17    <item name="materialCalendarStyle">@style/Widget.MaterialComponents.MaterialCalendar</item>
18    <item name="materialCalendarFullscreenTheme">@style/ThemeOverlay.MaterialComponents.MaterialCalendar.Fullscreen</item>
19    <item name="materialCalendarTheme">@style/ThemeOverlay.MaterialComponents.MaterialCalendar</item>
20</style>
21<activity
22        android:name=".DashboardActivity"
23        android:screenOrientation="portrait"
24        android:theme="@style/ScreenTheme"
25        android:windowSoftInputMode="stateAlwaysHidden" />
26

(4) Add the below code with a button click.

1 private val datePickerDialog by lazy {
2            DatePickerDialog(requireActivity(), R.style.SpinnerDatePickerDialog).apply {
3                setTitle(R.string.select_date)
4                datePicker.maxDate = LocalDate.now().minusDays(1).toMillis()
5                setOnDateSetListener { _, year, month, dayOfMonth ->
6                    viewModel.onDateSelected(year, month, dayOfMonth)
7                }
8            }
9        }
10    <!-- Base application theme. -->
11<style name="ScreenTheme" parent="Theme.MaterialComponents.Light.NoActionBar.Bridge">
12    <!-- Customize your theme here. -->
13    <item name="colorPrimary">@color/colorPrimary</item>
14    <item name="colorPrimaryDark">@color/colorPrimary</item>
15    <item name="colorAccent">@color/colorAccent</item>
16
17    <item name="materialCalendarStyle">@style/Widget.MaterialComponents.MaterialCalendar</item>
18    <item name="materialCalendarFullscreenTheme">@style/ThemeOverlay.MaterialComponents.MaterialCalendar.Fullscreen</item>
19    <item name="materialCalendarTheme">@style/ThemeOverlay.MaterialComponents.MaterialCalendar</item>
20</style>
21<activity
22        android:name=".DashboardActivity"
23        android:screenOrientation="portrait"
24        android:theme="@style/ScreenTheme"
25        android:windowSoftInputMode="stateAlwaysHidden" />
26val datePicker =
27                        MaterialDatePicker.Builder.datePicker()
28                                .setTitleText("Select date")
29                                .setSelection(MaterialDatePicker.todayInUtcMilliseconds())
30                                .build()
31
32                datePicker.show(childFragmentManager,"")
33
  • Use childFragmentManager if you want a calendar with fragment otherwise use supportFragmentManager with activity.

Output: enter image description here

Source https://stackoverflow.com/questions/71494291

QUESTION

Use selected element when selector allow for multiple options

Asked 2022-Mar-08 at 00:34

Sorry if my title is difficult to understand.

I've multiple fields named date1, date2... On Change of those fields, I want a full script to run. Today, I have simply copied the code for each dateN I have.

I would like to have a cleaner code and use the next JQuery selector:

1$("input[id^=date]")
2

The problem I face is that I don't know how to reuse the selected element into the subsequent code. I've tried with $(this) but it doesn't work, as it seems to be undefined.

Edit: as requested I show an example with $(this). The variable day stays empty. It works if I use the same selector as for month and year. The full example doesn't use $(this) yet but it's to show that my $(this) doesn't work.

1$("input[id^=date]")
2$("#date1").on("change", () => {
3      // Check validity of the date
4      const regexDate = /\d{2}\/\d{2}\/\d{4}/gm;
5      if (regexDate.test($("#date1").val()) == false) {
6        // Date format not valid, we quit the function
7        $("#info1").removeAttr("title");
8        $("#info1").hide();
9        return;
10      }
11
12      //Slice date
13      var day = $(this).val().substring(0, 2);
14      var month = $("#date1").val().substring(3, 5);
15      var year = $("#date1").val().substring(6, 10);
16
17      $.get("http://192.168.1.6:3000/getDateHistory/" + day + "/" + month + "/" + year, (data) => {
18        data = JSON.parse(data);
19        // Only display if not empty
20        if (data.length > 0) {
21          historyOfSameDate = "Other records exist at the same date: ";
22          for (var i = 0; i < data.length; i++) {
23            historyOfSameDate += data[i].desc + " - " + data[i].amount;
24            if (i < data.length - 1) {
25              historyOfSameDate += " | "
26            };
27          }
28          $("#info1").attr({
29            "title": historyOfSameDate
30          });
31          $("#info1").show();
32        } else {
33          $("#info1").removeAttr("title");
34          $("#info1").hide();
35
36        }
37      });
1$("input[id^=date]")
2$("#date1").on("change", () => {
3      // Check validity of the date
4      const regexDate = /\d{2}\/\d{2}\/\d{4}/gm;
5      if (regexDate.test($("#date1").val()) == false) {
6        // Date format not valid, we quit the function
7        $("#info1").removeAttr("title");
8        $("#info1").hide();
9        return;
10      }
11
12      //Slice date
13      var day = $(this).val().substring(0, 2);
14      var month = $("#date1").val().substring(3, 5);
15      var year = $("#date1").val().substring(6, 10);
16
17      $.get("http://192.168.1.6:3000/getDateHistory/" + day + "/" + month + "/" + year, (data) => {
18        data = JSON.parse(data);
19        // Only display if not empty
20        if (data.length > 0) {
21          historyOfSameDate = "Other records exist at the same date: ";
22          for (var i = 0; i < data.length; i++) {
23            historyOfSameDate += data[i].desc + " - " + data[i].amount;
24            if (i < data.length - 1) {
25              historyOfSameDate += " | "
26            };
27          }
28          $("#info1").attr({
29            "title": historyOfSameDate
30          });
31          $("#info1").show();
32        } else {
33          $("#info1").removeAttr("title");
34          $("#info1").hide();
35
36        }
37      });<tr>
38  <td><input class="form-control datepicker" id="date1" placeholder="Enter date"></td>
39  <td style="vertical-align:middle;"><i id="info1" class="bi bi-info-square-fill"></i></td>
40  <td>
41    <select class="form-control" id="type1" placeholder="Enter type">
42      <option value=""></option>
43    </select>
44  </td>
45  <!-- Options dynamically created -->
46  <td><input class="form-control" id="desc1" placeholder="Enter description"></td>
47  <td><input class="form-control" id="amount1" placeholder="Enter amount"></td>
48  <td>
49    <select class="form-control" id="payer1" placeholder="Enter type">
50      <option value=""></option>
51    </select>
52  </td>
53  <!-- Options dynamically created -->
54  <td>
55    <select class="form-control" id="paymentsource1" placeholder="Enter type">
56      <option value=""></option>
57    </select>
58  </td>
59  <!-- Options dynamically created -->
60  <td style="vertical-align:middle; color:orange;"><i id="warning1" class="bi bi-exclamation-triangle-fill" title="This record will be ignored because it either doesn't contain enough information or contains error(s)."></i></td>
61</tr>
62<tr>
63  <td><input class="form-control datepicker" id="date2" placeholder="Enter date"></td>
64  <td style="vertical-align:middle;"><i id="info2" class="bi bi-info-square-fill"></i></td>
65  <td>
66    <select class="form-control" id="type2" placeholder="Enter type">
67      <option value=""></option>
68    </select>
69  </td>
70  <!-- Options dynamically created -->
71  <td><input class="form-control" id="desc2" placeholder="Enter description"></td>
72  <td><input class="form-control" id="amount2" placeholder="Enter amount"></td>
73  <td>
74    <select class="form-control" id="payer2" placeholder="Enter type">
75      <option value=""></option>
76    </select>
77  </td>
78  <!-- Options dynamically created -->
79  <td>
80    <select class="form-control" id="paymentsource2" placeholder="Enter type">
81      <option value=""></option>
82    </select>
83  </td>
84  <!-- Options dynamically created -->
85  <td>

Thank you

ANSWER

Answered 2022-Feb-27 at 11:42

Use it like this:

1$("input[id^=date]")
2$("#date1").on("change", () => {
3      // Check validity of the date
4      const regexDate = /\d{2}\/\d{2}\/\d{4}/gm;
5      if (regexDate.test($("#date1").val()) == false) {
6        // Date format not valid, we quit the function
7        $("#info1").removeAttr("title");
8        $("#info1").hide();
9        return;
10      }
11
12      //Slice date
13      var day = $(this).val().substring(0, 2);
14      var month = $("#date1").val().substring(3, 5);
15      var year = $("#date1").val().substring(6, 10);
16
17      $.get("http://192.168.1.6:3000/getDateHistory/" + day + "/" + month + "/" + year, (data) => {
18        data = JSON.parse(data);
19        // Only display if not empty
20        if (data.length > 0) {
21          historyOfSameDate = "Other records exist at the same date: ";
22          for (var i = 0; i < data.length; i++) {
23            historyOfSameDate += data[i].desc + " - " + data[i].amount;
24            if (i < data.length - 1) {
25              historyOfSameDate += " | "
26            };
27          }
28          $("#info1").attr({
29            "title": historyOfSameDate
30          });
31          $("#info1").show();
32        } else {
33          $("#info1").removeAttr("title");
34          $("#info1").hide();
35
36        }
37      });<tr>
38  <td><input class="form-control datepicker" id="date1" placeholder="Enter date"></td>
39  <td style="vertical-align:middle;"><i id="info1" class="bi bi-info-square-fill"></i></td>
40  <td>
41    <select class="form-control" id="type1" placeholder="Enter type">
42      <option value=""></option>
43    </select>
44  </td>
45  <!-- Options dynamically created -->
46  <td><input class="form-control" id="desc1" placeholder="Enter description"></td>
47  <td><input class="form-control" id="amount1" placeholder="Enter amount"></td>
48  <td>
49    <select class="form-control" id="payer1" placeholder="Enter type">
50      <option value=""></option>
51    </select>
52  </td>
53  <!-- Options dynamically created -->
54  <td>
55    <select class="form-control" id="paymentsource1" placeholder="Enter type">
56      <option value=""></option>
57    </select>
58  </td>
59  <!-- Options dynamically created -->
60  <td style="vertical-align:middle; color:orange;"><i id="warning1" class="bi bi-exclamation-triangle-fill" title="This record will be ignored because it either doesn't contain enough information or contains error(s)."></i></td>
61</tr>
62<tr>
63  <td><input class="form-control datepicker" id="date2" placeholder="Enter date"></td>
64  <td style="vertical-align:middle;"><i id="info2" class="bi bi-info-square-fill"></i></td>
65  <td>
66    <select class="form-control" id="type2" placeholder="Enter type">
67      <option value=""></option>
68    </select>
69  </td>
70  <!-- Options dynamically created -->
71  <td><input class="form-control" id="desc2" placeholder="Enter description"></td>
72  <td><input class="form-control" id="amount2" placeholder="Enter amount"></td>
73  <td>
74    <select class="form-control" id="payer2" placeholder="Enter type">
75      <option value=""></option>
76    </select>
77  </td>
78  <!-- Options dynamically created -->
79  <td>
80    <select class="form-control" id="paymentsource2" placeholder="Enter type">
81      <option value=""></option>
82    </select>
83  </td>
84  <!-- Options dynamically created -->
85  <td>$('input[type=date]').click(function() {
86    var fields = $(this);
87    // do something with it
88    return false;
89});
90

Source https://stackoverflow.com/questions/71272202

QUESTION

Dynamic form returns the same value for the first and second input

Asked 2022-Feb-25 at 09:47

I'm creating a custom dynamic form using Material UI https://mui.com/ library as the component for my React Js app.

Here is the initial state of the dynamic form component. enter image description here

As we can see that the dynamic form component starts only with one delivery point form. We could add another delivery point form by clicking the "Add Delivery" button. Here is the example after clicking the "Add Delivery" button.

enter image description here

The problem is: the first form and the second form have the same values (if there are more than 1 form) after we gave input to one of the first or second forms as seen in the screenshot below. This is not the condition I want.

enter image description here

But the rest (third, fourth, and so on) forms are unique as seen in the screenshot below. This is the condition I want.

enter image description here

Here is the simple working code:

DeliveryPoint.jsx

1const DeliveryPoint = (props) => {
2  const {
3    initialFormObject,
4    formObject,
5    setFormObject,
6    collapseObject,
7    setCollapseObject
8  } = props;
9
10  const classes = useStyles();
11
12  const deliveryPointBaseObject = initialFormObject.deliveryPointList[0];
13
14  const handleFormObjectChange = (inputEvent, inputIndex) => {
15    let deliveryPointListData = [...formObject.deliveryPointList];
16    deliveryPointListData[inputIndex][inputEvent.target.name] =
17      inputEvent.target.value;
18
19    setFormObject((current) => ({
20      ...current,
21      deliveryPointList: deliveryPointListData
22    }));
23  };
24
25  const handleDatePickerChange = (inputNewValue, inputIndex) => {
26    let deliveryPointListData = [...formObject.deliveryPointList];
27    deliveryPointListData[inputIndex].deliveryDate = inputNewValue;
28
29    setFormObject((current) => ({
30      ...current,
31      deliveryPointList: deliveryPointListData
32    }));
33  };
34
35  const handleCollapseChange = (inputIndex) => {
36    let deliveryPointListData = [...collapseObject.deliveryPointList];
37    deliveryPointListData[inputIndex] = !deliveryPointListData[inputIndex];
38
39    setCollapseObject((current) => ({
40      ...current,
41      deliveryPointList: deliveryPointListData
42    }));
43  };
44
45  const handleAddFormItemButtonClick = () => {
46    let deliveryPointListData = [...formObject.deliveryPointList];
47    deliveryPointListData.push(deliveryPointBaseObject);
48
49    setFormObject((current) => ({
50      ...current,
51      deliveryPointList: deliveryPointListData
52    }));
53
54    deliveryPointListData = [...collapseObject.deliveryPointList];
55    deliveryPointListData.push(false);
56
57    setCollapseObject((current) => ({
58      ...current,
59      deliveryPointList: deliveryPointListData
60    }));
61  };
62
63  const handleDeleteFormItemButtonClick = (inputIndex) => {
64    let deliveryPointListData = [...formObject.deliveryPointList];
65    deliveryPointListData.splice(inputIndex, 1);
66
67    setFormObject((current) => ({
68      ...current,
69      deliveryPointList: deliveryPointListData
70    }));
71
72    deliveryPointListData = [...collapseObject.deliveryPointList];
73    deliveryPointListData.splice(inputIndex, 1);
74
75    setCollapseObject((current) => ({
76      ...current,
77      deliveryPointList: deliveryPointListData
78    }));
79  };
80
81  return (
82    <>
83      {formObject.deliveryPointList.map((item, index) => (
84        <Box key={index} className={classes.formItemContainer}>
85          <Box className={classes.formItemTitleContainer}>
86            {/* TITLE */}
87            <Typography variant="h6">
88              {index === 0 ? `Delivery point` : `#${index + 1} Delivery point`}
89            </Typography>
90
91            {/* ADD OR DELETE BUTTON */}
92            {index === 0 ? (
93              <Button
94                className={classes.formItemTitleButton}
95                variant="outlined"
96                startIcon={<IconAdd />}
97                onClick={handleAddFormItemButtonClick}
98              >
99                Add Delivery
100              </Button>
101            ) : (
102              <Button
103                className={classes.formItemTitleButton}
104                variant="outlined"
105                startIcon={<IconRemove />}
106                color="error"
107                onClick={() => handleDeleteFormItemButtonClick(index)}
108              >
109                Remove Delivery
110              </Button>
111            )}
112          </Box>
113
114          {/* CONSIGNEE */}
115          <FormControl
116            required
117            variant="outlined"
118            className={classes.formItemInput}
119          >
120            <InputLabel>Consignee</InputLabel>
121
122            <OutlinedInput
123              label="Consignee"
124              type="text"
125              name="consignee"
126              value={item.consignee}
127              onChange={(event) => handleFormObjectChange(event, index)}
128            />
129
130            <FormHelperText>
131              Search for name, street, city, or state by typing in the box.
132            </FormHelperText>
133          </FormControl>
134
135          {/* DELIVERY DATE */}
136          <LocalizationProvider dateAdapter={AdapterDateFns}>
137            <DatePicker
138              disableFuture
139              label="Select Delivery Date"
140              openTo="year"
141              views={["year", "month", "day"]}
142              value={item.deliveryDate}
143              onChange={(newValue) => handleDatePickerChange(newValue, index)}
144              renderInput={(params) => (
145                <TextField
146                  required
147                  className={classes.formItemInput}
148                  {...params}
149                />
150              )}
151            />
152          </LocalizationProvider>
153
154          {/* COLLAPSE */}
155          <Collapse
156            in={collapseObject.deliveryPointList[index]}
157            timeout="auto"
158            unmountOnExit
159            className={classes.formItemCollapse}
160          >
161            {/* DELIVERY INSTRUCTION */}
162            <FormControl variant="outlined" className={classes.formItemInput}>
163              <InputLabel>Delivery Instructions</InputLabel>
164
165              <OutlinedInput
166                label="Delivery Instructions"
167                type="text"
168                name="deliveryInstruction"
169                value={item.deliveryInstruction}
170                onChange={(event) => handleFormObjectChange(event, index)}
171              />
172            </FormControl>
173          </Collapse>
174
175          {/* EXPAND BUTTON */}
176          <Button
177            variant="contained"
178            disableElevation
179            startIcon={
180              collapseObject.deliveryPoint ? (
181                <IconArrowDropUp />
182              ) : (
183                <IconArrowDropDown />
184              )
185            }
186            className={classes.formItemButtonExpand}
187            onClick={() => handleCollapseChange(index)}
188          >
189            {collapseObject.deliveryPoint
190              ? "Hide full data entry"
191              : "Fill in more complete data?"}
192          </Button>
193        </Box>
194      ))}
195    </>
196  );
197};
198
199export default DeliveryPoint;
200

App.jsx

1const DeliveryPoint = (props) => {
2  const {
3    initialFormObject,
4    formObject,
5    setFormObject,
6    collapseObject,
7    setCollapseObject
8  } = props;
9
10  const classes = useStyles();
11
12  const deliveryPointBaseObject = initialFormObject.deliveryPointList[0];
13
14  const handleFormObjectChange = (inputEvent, inputIndex) => {
15    let deliveryPointListData = [...formObject.deliveryPointList];
16    deliveryPointListData[inputIndex][inputEvent.target.name] =
17      inputEvent.target.value;
18
19    setFormObject((current) => ({
20      ...current,
21      deliveryPointList: deliveryPointListData
22    }));
23  };
24
25  const handleDatePickerChange = (inputNewValue, inputIndex) => {
26    let deliveryPointListData = [...formObject.deliveryPointList];
27    deliveryPointListData[inputIndex].deliveryDate = inputNewValue;
28
29    setFormObject((current) => ({
30      ...current,
31      deliveryPointList: deliveryPointListData
32    }));
33  };
34
35  const handleCollapseChange = (inputIndex) => {
36    let deliveryPointListData = [...collapseObject.deliveryPointList];
37    deliveryPointListData[inputIndex] = !deliveryPointListData[inputIndex];
38
39    setCollapseObject((current) => ({
40      ...current,
41      deliveryPointList: deliveryPointListData
42    }));
43  };
44
45  const handleAddFormItemButtonClick = () => {
46    let deliveryPointListData = [...formObject.deliveryPointList];
47    deliveryPointListData.push(deliveryPointBaseObject);
48
49    setFormObject((current) => ({
50      ...current,
51      deliveryPointList: deliveryPointListData
52    }));
53
54    deliveryPointListData = [...collapseObject.deliveryPointList];
55    deliveryPointListData.push(false);
56
57    setCollapseObject((current) => ({
58      ...current,
59      deliveryPointList: deliveryPointListData
60    }));
61  };
62
63  const handleDeleteFormItemButtonClick = (inputIndex) => {
64    let deliveryPointListData = [...formObject.deliveryPointList];
65    deliveryPointListData.splice(inputIndex, 1);
66
67    setFormObject((current) => ({
68      ...current,
69      deliveryPointList: deliveryPointListData
70    }));
71
72    deliveryPointListData = [...collapseObject.deliveryPointList];
73    deliveryPointListData.splice(inputIndex, 1);
74
75    setCollapseObject((current) => ({
76      ...current,
77      deliveryPointList: deliveryPointListData
78    }));
79  };
80
81  return (
82    <>
83      {formObject.deliveryPointList.map((item, index) => (
84        <Box key={index} className={classes.formItemContainer}>
85          <Box className={classes.formItemTitleContainer}>
86            {/* TITLE */}
87            <Typography variant="h6">
88              {index === 0 ? `Delivery point` : `#${index + 1} Delivery point`}
89            </Typography>
90
91            {/* ADD OR DELETE BUTTON */}
92            {index === 0 ? (
93              <Button
94                className={classes.formItemTitleButton}
95                variant="outlined"
96                startIcon={<IconAdd />}
97                onClick={handleAddFormItemButtonClick}
98              >
99                Add Delivery
100              </Button>
101            ) : (
102              <Button
103                className={classes.formItemTitleButton}
104                variant="outlined"
105                startIcon={<IconRemove />}
106                color="error"
107                onClick={() => handleDeleteFormItemButtonClick(index)}
108              >
109                Remove Delivery
110              </Button>
111            )}
112          </Box>
113
114          {/* CONSIGNEE */}
115          <FormControl
116            required
117            variant="outlined"
118            className={classes.formItemInput}
119          >
120            <InputLabel>Consignee</InputLabel>
121
122            <OutlinedInput
123              label="Consignee"
124              type="text"
125              name="consignee"
126              value={item.consignee}
127              onChange={(event) => handleFormObjectChange(event, index)}
128            />
129
130            <FormHelperText>
131              Search for name, street, city, or state by typing in the box.
132            </FormHelperText>
133          </FormControl>
134
135          {/* DELIVERY DATE */}
136          <LocalizationProvider dateAdapter={AdapterDateFns}>
137            <DatePicker
138              disableFuture
139              label="Select Delivery Date"
140              openTo="year"
141              views={["year", "month", "day"]}
142              value={item.deliveryDate}
143              onChange={(newValue) => handleDatePickerChange(newValue, index)}
144              renderInput={(params) => (
145                <TextField
146                  required
147                  className={classes.formItemInput}
148                  {...params}
149                />
150              )}
151            />
152          </LocalizationProvider>
153
154          {/* COLLAPSE */}
155          <Collapse
156            in={collapseObject.deliveryPointList[index]}
157            timeout="auto"
158            unmountOnExit
159            className={classes.formItemCollapse}
160          >
161            {/* DELIVERY INSTRUCTION */}
162            <FormControl variant="outlined" className={classes.formItemInput}>
163              <InputLabel>Delivery Instructions</InputLabel>
164
165              <OutlinedInput
166                label="Delivery Instructions"
167                type="text"
168                name="deliveryInstruction"
169                value={item.deliveryInstruction}
170                onChange={(event) => handleFormObjectChange(event, index)}
171              />
172            </FormControl>
173          </Collapse>
174
175          {/* EXPAND BUTTON */}
176          <Button
177            variant="contained"
178            disableElevation
179            startIcon={
180              collapseObject.deliveryPoint ? (
181                <IconArrowDropUp />
182              ) : (
183                <IconArrowDropDown />
184              )
185            }
186            className={classes.formItemButtonExpand}
187            onClick={() => handleCollapseChange(index)}
188          >
189            {collapseObject.deliveryPoint
190              ? "Hide full data entry"
191              : "Fill in more complete data?"}
192          </Button>
193        </Box>
194      ))}
195    </>
196  );
197};
198
199export default DeliveryPoint;
200const App = () => {
201  const classes = useStyles();
202
203  const initialFormObject = {
204    // DELIVERY POINT
205    deliveryPointList: [
206      {
207        consignee: "",
208        deliveryDate: new Date(),
209        deliveryInstruction: ""
210      }
211    ]
212    // OTHER OBJECT ITEMS HERE
213  };
214
215  const initialCollapseObject = {
216    deliveryPointList: [false]
217    // OTHER LIST ITEMS HERE
218  };
219
220  const [formObject, setFormObject] = useState(initialFormObject);
221  const [collapseObject, setCollapseObject] = useState(initialCollapseObject);
222
223  return (
224    <Box className={classes.pageRoot}>
225      {/* FORM */}
226      <Box className={classes.formContainer}>
227        {/* DELIVERY POINT */}
228        <DeliveryPoint
229          initialFormObject={initialFormObject}
230          formObject={formObject}
231          setFormObject={setFormObject}
232          collapseObject={collapseObject}
233          setCollapseObject={setCollapseObject}
234        />
235      </Box>
236    </Box>
237  );
238};
239
240export default App;
241

Here is the full demo https://codesandbox.io/s/stackoverflow-dynamic-form-wxrmd0

Steps to reproduce:

  1. Click the "Add Delivery" button twice. So there will be 3 delivery point forms.
  2. Change the "consignee" or the "delivery date" in the first delivery point form. Therefore, the second delivery point form will have the same value as the first form.

What's wrong with my state management and what's the solution for this?

Note: you can assume the OultinedInput component from Material UI as an HTML input element.

ANSWER

Answered 2022-Feb-25 at 09:40
Issue

You are mutating the state in your handleFormObjectChange and handleDatePickerChange handlers.

1const DeliveryPoint = (props) => {
2  const {
3    initialFormObject,
4    formObject,
5    setFormObject,
6    collapseObject,
7    setCollapseObject
8  } = props;
9
10  const classes = useStyles();
11
12  const deliveryPointBaseObject = initialFormObject.deliveryPointList[0];
13
14  const handleFormObjectChange = (inputEvent, inputIndex) => {
15    let deliveryPointListData = [...formObject.deliveryPointList];
16    deliveryPointListData[inputIndex][inputEvent.target.name] =
17      inputEvent.target.value;
18
19    setFormObject((current) => ({
20      ...current,
21      deliveryPointList: deliveryPointListData
22    }));
23  };
24
25  const handleDatePickerChange = (inputNewValue, inputIndex) => {
26    let deliveryPointListData = [...formObject.deliveryPointList];
27    deliveryPointListData[inputIndex].deliveryDate = inputNewValue;
28
29    setFormObject((current) => ({
30      ...current,
31      deliveryPointList: deliveryPointListData
32    }));
33  };
34
35  const handleCollapseChange = (inputIndex) => {
36    let deliveryPointListData = [...collapseObject.deliveryPointList];
37    deliveryPointListData[inputIndex] = !deliveryPointListData[inputIndex];
38
39    setCollapseObject((current) => ({
40      ...current,
41      deliveryPointList: deliveryPointListData
42    }));
43  };
44
45  const handleAddFormItemButtonClick = () => {
46    let deliveryPointListData = [...formObject.deliveryPointList];
47    deliveryPointListData.push(deliveryPointBaseObject);
48
49    setFormObject((current) => ({
50      ...current,
51      deliveryPointList: deliveryPointListData
52    }));
53
54    deliveryPointListData = [...collapseObject.deliveryPointList];
55    deliveryPointListData.push(false);
56
57    setCollapseObject((current) => ({
58      ...current,
59      deliveryPointList: deliveryPointListData
60    }));
61  };
62
63  const handleDeleteFormItemButtonClick = (inputIndex) => {
64    let deliveryPointListData = [...formObject.deliveryPointList];
65    deliveryPointListData.splice(inputIndex, 1);
66
67    setFormObject((current) => ({
68      ...current,
69      deliveryPointList: deliveryPointListData
70    }));
71
72    deliveryPointListData = [...collapseObject.deliveryPointList];
73    deliveryPointListData.splice(inputIndex, 1);
74
75    setCollapseObject((current) => ({
76      ...current,
77      deliveryPointList: deliveryPointListData
78    }));
79  };
80
81  return (
82    <>
83      {formObject.deliveryPointList.map((item, index) => (
84        <Box key={index} className={classes.formItemContainer}>
85          <Box className={classes.formItemTitleContainer}>
86            {/* TITLE */}
87            <Typography variant="h6">
88              {index === 0 ? `Delivery point` : `#${index + 1} Delivery point`}
89            </Typography>
90
91            {/* ADD OR DELETE BUTTON */}
92            {index === 0 ? (
93              <Button
94                className={classes.formItemTitleButton}
95                variant="outlined"
96                startIcon={<IconAdd />}
97                onClick={handleAddFormItemButtonClick}
98              >
99                Add Delivery
100              </Button>
101            ) : (
102              <Button
103                className={classes.formItemTitleButton}
104                variant="outlined"
105                startIcon={<IconRemove />}
106                color="error"
107                onClick={() => handleDeleteFormItemButtonClick(index)}
108              >
109                Remove Delivery
110              </Button>
111            )}
112          </Box>
113
114          {/* CONSIGNEE */}
115          <FormControl
116            required
117            variant="outlined"
118            className={classes.formItemInput}
119          >
120            <InputLabel>Consignee</InputLabel>
121
122            <OutlinedInput
123              label="Consignee"
124              type="text"
125              name="consignee"
126              value={item.consignee}
127              onChange={(event) => handleFormObjectChange(event, index)}
128            />
129
130            <FormHelperText>
131              Search for name, street, city, or state by typing in the box.
132            </FormHelperText>
133          </FormControl>
134
135          {/* DELIVERY DATE */}
136          <LocalizationProvider dateAdapter={AdapterDateFns}>
137            <DatePicker
138              disableFuture
139              label="Select Delivery Date"
140              openTo="year"
141              views={["year", "month", "day"]}
142              value={item.deliveryDate}
143              onChange={(newValue) => handleDatePickerChange(newValue, index)}
144              renderInput={(params) => (
145                <TextField
146                  required
147                  className={classes.formItemInput}
148                  {...params}
149                />
150              )}
151            />
152          </LocalizationProvider>
153
154          {/* COLLAPSE */}
155          <Collapse
156            in={collapseObject.deliveryPointList[index]}
157            timeout="auto"
158            unmountOnExit
159            className={classes.formItemCollapse}
160          >
161            {/* DELIVERY INSTRUCTION */}
162            <FormControl variant="outlined" className={classes.formItemInput}>
163              <InputLabel>Delivery Instructions</InputLabel>
164
165              <OutlinedInput
166                label="Delivery Instructions"
167                type="text"
168                name="deliveryInstruction"
169                value={item.deliveryInstruction}
170                onChange={(event) => handleFormObjectChange(event, index)}
171              />
172            </FormControl>
173          </Collapse>
174
175          {/* EXPAND BUTTON */}
176          <Button
177            variant="contained"
178            disableElevation
179            startIcon={
180              collapseObject.deliveryPoint ? (
181                <IconArrowDropUp />
182              ) : (
183                <IconArrowDropDown />
184              )
185            }
186            className={classes.formItemButtonExpand}
187            onClick={() => handleCollapseChange(index)}
188          >
189            {collapseObject.deliveryPoint
190              ? "Hide full data entry"
191              : "Fill in more complete data?"}
192          </Button>
193        </Box>
194      ))}
195    </>
196  );
197};
198
199export default DeliveryPoint;
200const App = () => {
201  const classes = useStyles();
202
203  const initialFormObject = {
204    // DELIVERY POINT
205    deliveryPointList: [
206      {
207        consignee: "",
208        deliveryDate: new Date(),
209        deliveryInstruction: ""
210      }
211    ]
212    // OTHER OBJECT ITEMS HERE
213  };
214
215  const initialCollapseObject = {
216    deliveryPointList: [false]
217    // OTHER LIST ITEMS HERE
218  };
219
220  const [formObject, setFormObject] = useState(initialFormObject);
221  const [collapseObject, setCollapseObject] = useState(initialCollapseObject);
222
223  return (
224    <Box className={classes.pageRoot}>
225      {/* FORM */}
226      <Box className={classes.formContainer}>
227        {/* DELIVERY POINT */}
228        <DeliveryPoint
229          initialFormObject={initialFormObject}
230          formObject={formObject}
231          setFormObject={setFormObject}
232          collapseObject={collapseObject}
233          setCollapseObject={setCollapseObject}
234        />
235      </Box>
236    </Box>
237  );
238};
239
240export default App;
241const handleFormObjectChange = (inputEvent, inputIndex) => {
242  let deliveryPointListData = [...formObject.deliveryPointList];
243
244  // Mutates the nested property!!
245  deliveryPointListData[inputIndex][inputEvent.target.name] =
246    inputEvent.target.value;
247
248  setFormObject((current) => ({
249    ...current,
250    deliveryPointList: deliveryPointListData
251  }));
252};
253
254const handleDatePickerChange = (inputNewValue, inputIndex) => {
255  let deliveryPointListData = [...formObject.deliveryPointList];
256
257  // Mutates the nested property!!
258  deliveryPointListData[inputIndex].deliveryDate = inputNewValue;
259
260  setFormObject((current) => ({
261    ...current,
262    deliveryPointList: deliveryPointListData
263  }));
264};
265
Solution

Ensure you are shallow copying all properties and nested properties that are being updated. This ensures all updates create new object references.

1const DeliveryPoint = (props) => {
2  const {
3    initialFormObject,
4    formObject,
5    setFormObject,
6    collapseObject,
7    setCollapseObject
8  } = props;
9
10  const classes = useStyles();
11
12  const deliveryPointBaseObject = initialFormObject.deliveryPointList[0];
13
14  const handleFormObjectChange = (inputEvent, inputIndex) => {
15    let deliveryPointListData = [...formObject.deliveryPointList];
16    deliveryPointListData[inputIndex][inputEvent.target.name] =
17      inputEvent.target.value;
18
19    setFormObject((current) => ({
20      ...current,
21      deliveryPointList: deliveryPointListData
22    }));
23  };
24
25  const handleDatePickerChange = (inputNewValue, inputIndex) => {
26    let deliveryPointListData = [...formObject.deliveryPointList];
27    deliveryPointListData[inputIndex].deliveryDate = inputNewValue;
28
29    setFormObject((current) => ({
30      ...current,
31      deliveryPointList: deliveryPointListData
32    }));
33  };
34
35  const handleCollapseChange = (inputIndex) => {
36    let deliveryPointListData = [...collapseObject.deliveryPointList];
37    deliveryPointListData[inputIndex] = !deliveryPointListData[inputIndex];
38
39    setCollapseObject((current) => ({
40      ...current,
41      deliveryPointList: deliveryPointListData
42    }));
43  };
44
45  const handleAddFormItemButtonClick = () => {
46    let deliveryPointListData = [...formObject.deliveryPointList];
47    deliveryPointListData.push(deliveryPointBaseObject);
48
49    setFormObject((current) => ({
50      ...current,
51      deliveryPointList: deliveryPointListData
52    }));
53
54    deliveryPointListData = [...collapseObject.deliveryPointList];
55    deliveryPointListData.push(false);
56
57    setCollapseObject((current) => ({
58      ...current,
59      deliveryPointList: deliveryPointListData
60    }));
61  };
62
63  const handleDeleteFormItemButtonClick = (inputIndex) => {
64    let deliveryPointListData = [...formObject.deliveryPointList];
65    deliveryPointListData.splice(inputIndex, 1);
66
67    setFormObject((current) => ({
68      ...current,
69      deliveryPointList: deliveryPointListData
70    }));
71
72    deliveryPointListData = [...collapseObject.deliveryPointList];
73    deliveryPointListData.splice(inputIndex, 1);
74
75    setCollapseObject((current) => ({
76      ...current,
77      deliveryPointList: deliveryPointListData
78    }));
79  };
80
81  return (
82    <>
83      {formObject.deliveryPointList.map((item, index) => (
84        <Box key={index} className={classes.formItemContainer}>
85          <Box className={classes.formItemTitleContainer}>
86            {/* TITLE */}
87            <Typography variant="h6">
88              {index === 0 ? `Delivery point` : `#${index + 1} Delivery point`}
89            </Typography>
90
91            {/* ADD OR DELETE BUTTON */}
92            {index === 0 ? (
93              <Button
94                className={classes.formItemTitleButton}
95                variant="outlined"
96                startIcon={<IconAdd />}
97                onClick={handleAddFormItemButtonClick}
98              >
99                Add Delivery
100              </Button>
101            ) : (
102              <Button
103                className={classes.formItemTitleButton}
104                variant="outlined"
105                startIcon={<IconRemove />}
106                color="error"
107                onClick={() => handleDeleteFormItemButtonClick(index)}
108              >
109                Remove Delivery
110              </Button>
111            )}
112          </Box>
113
114          {/* CONSIGNEE */}
115          <FormControl
116            required
117            variant="outlined"
118            className={classes.formItemInput}
119          >
120            <InputLabel>Consignee</InputLabel>
121
122            <OutlinedInput
123              label="Consignee"
124              type="text"
125              name="consignee"
126              value={item.consignee}
127              onChange={(event) => handleFormObjectChange(event, index)}
128            />
129
130            <FormHelperText>
131              Search for name, street, city, or state by typing in the box.
132            </FormHelperText>
133          </FormControl>
134
135          {/* DELIVERY DATE */}
136          <LocalizationProvider dateAdapter={AdapterDateFns}>
137            <DatePicker
138              disableFuture
139              label="Select Delivery Date"
140              openTo="year"
141              views={["year", "month", "day"]}
142              value={item.deliveryDate}
143              onChange={(newValue) => handleDatePickerChange(newValue, index)}
144              renderInput={(params) => (
145                <TextField
146                  required
147                  className={classes.formItemInput}
148                  {...params}
149                />
150              )}
151            />
152          </LocalizationProvider>
153
154          {/* COLLAPSE */}
155          <Collapse
156            in={collapseObject.deliveryPointList[index]}
157            timeout="auto"
158            unmountOnExit
159            className={classes.formItemCollapse}
160          >
161            {/* DELIVERY INSTRUCTION */}
162            <FormControl variant="outlined" className={classes.formItemInput}>
163              <InputLabel>Delivery Instructions</InputLabel>
164
165              <OutlinedInput
166                label="Delivery Instructions"
167                type="text"
168                name="deliveryInstruction"
169                value={item.deliveryInstruction}
170                onChange={(event) => handleFormObjectChange(event, index)}
171              />
172            </FormControl>
173          </Collapse>
174
175          {/* EXPAND BUTTON */}
176          <Button
177            variant="contained"
178            disableElevation
179            startIcon={
180              collapseObject.deliveryPoint ? (
181                <IconArrowDropUp />
182              ) : (
183                <IconArrowDropDown />
184              )
185            }
186            className={classes.formItemButtonExpand}
187            onClick={() => handleCollapseChange(index)}
188          >
189            {collapseObject.deliveryPoint
190              ? "Hide full data entry"
191              : "Fill in more complete data?"}
192          </Button>
193        </Box>
194      ))}
195    </>
196  );
197};
198
199export default DeliveryPoint;
200const App = () => {
201  const classes = useStyles();
202
203  const initialFormObject = {
204    // DELIVERY POINT
205    deliveryPointList: [
206      {
207        consignee: "",
208        deliveryDate: new Date(),
209        deliveryInstruction: ""
210      }
211    ]
212    // OTHER OBJECT ITEMS HERE
213  };
214
215  const initialCollapseObject = {
216    deliveryPointList: [false]
217    // OTHER LIST ITEMS HERE
218  };
219
220  const [formObject, setFormObject] = useState(initialFormObject);
221  const [collapseObject, setCollapseObject] = useState(initialCollapseObject);
222
223  return (
224    <Box className={classes.pageRoot}>
225      {/* FORM */}
226      <Box className={classes.formContainer}>
227        {/* DELIVERY POINT */}
228        <DeliveryPoint
229          initialFormObject={initialFormObject}
230          formObject={formObject}
231          setFormObject={setFormObject}
232          collapseObject={collapseObject}
233          setCollapseObject={setCollapseObject}
234        />
235      </Box>
236    </Box>
237  );
238};
239
240export default App;
241const handleFormObjectChange = (inputEvent, inputIndex) => {
242  let deliveryPointListData = [...formObject.deliveryPointList];
243
244  // Mutates the nested property!!
245  deliveryPointListData[inputIndex][inputEvent.target.name] =
246    inputEvent.target.value;
247
248  setFormObject((current) => ({
249    ...current,
250    deliveryPointList: deliveryPointListData
251  }));
252};
253
254const handleDatePickerChange = (inputNewValue, inputIndex) => {
255  let deliveryPointListData = [...formObject.deliveryPointList];
256
257  // Mutates the nested property!!
258  deliveryPointListData[inputIndex].deliveryDate = inputNewValue;
259
260  setFormObject((current) => ({
261    ...current,
262    deliveryPointList: deliveryPointListData
263  }));
264};
265const handleFormObjectChange = (inputEvent, inputIndex) => {
266  let deliveryPointListData = [...formObject.deliveryPointList];
267
268  deliveryPointListData[inputIndex] = {
269    ...deliveryPointListData[inputIndex], // <-- shallow copy
270    [inputEvent.target.name]: inputEvent.target.value
271  };
272
273  setFormObject((current) => ({
274    ...current,
275    deliveryPointList: deliveryPointListData
276  }));
277};
278
279const handleDatePickerChange = (inputNewValue, inputIndex) => {
280  let deliveryPointListData = [...formObject.deliveryPointList];
281
282  deliveryPointListData[inputIndex] = {
283    ...deliveryPointListData[inputIndex], // <-- shallow copy
284    deliveryDate: inputNewValue,
285  };
286
287  setFormObject((current) => ({
288    ...current,
289    deliveryPointList: deliveryPointListData
290  }));
291};
292

Edit dynamic-form-returns-the-same-value-for-the-first-and-second-input

Source https://stackoverflow.com/questions/71263503

QUESTION

Pass data from the model to js for a specific day and time

Asked 2022-Feb-23 at 16:12

I have a model in which we can choose the opening hours of the institution for each day of the week, from such and such to such and such, for example Monday 12:00 AM - 11:30 PM

1<?php
2
3namespace common\models;
4
5use yii\behaviors\TimestampBehavior;
6use yii\db\ActiveRecord;
7use yii\db\Expression;
8
9class WorkHours extends _source_WorkHours
10{
11    public const WEEK_DAY_MON = 'Mon';
12    public const WEEK_DAY_TUE = 'Tue';
13    public const WEEK_DAY_WED = 'Wed';
14    public const WEEK_DAY_THU = 'Thu';
15    public const WEEK_DAY_FRI = 'Fri';
16    public const WEEK_DAY_SAT = 'Sat';
17    public const WEEK_DAY_SUN = 'Sun';
18
19
20    /**
21     * {@inheritdoc}
22     */
23    public function behaviors(): array
24    {
25        return [
26            'timestamp' => [
27                'class'      => TimestampBehavior::class,
28                'attributes' => [
29                    ActiveRecord::EVENT_BEFORE_INSERT => ['created_at'],
30                ],
31                'value'      => new Expression('NOW()'),
32            ],
33        ];
34    }
35
36    public static function weekDays(): array
37    {
38        return [
39            self::WEEK_DAY_MON => 'Monday',
40            self::WEEK_DAY_TUE => 'Tuesday',
41            self::WEEK_DAY_WED => 'Wednesday',
42            self::WEEK_DAY_THU => 'Thursday',
43            self::WEEK_DAY_FRI => 'Friday',
44            self::WEEK_DAY_SAT => 'Saturday',
45            self::WEEK_DAY_SUN => 'Sunday',
46        ];
47    }
48
49    public static function getWeekDay(string $val): string
50    {
51        $ar = self::weekDays();
52
53        return $ar[$val] ?? $val;
54    }
55
56    public static function hoursList(): array
57    {
58        $list = [];
59        for ($i = 0; $i < 24; $i++) {
60            $A = 'AM';
61            $n = $i;
62            if ($i >= 12) {
63                $A = 'PM';
64                $n = $i - 12;
65            }
66
67            $n = $n < 10 ? '0' . $n : $n;
68            $_A = ($i === 12 ? 'AM' : $A);
69            $list[$i . '.00'] = $n . '.00 ' . ($i === 0 ? 'PM' : $_A);
70            $list[$i . '.30'] = $n . '.30 ' . $A;
71        }
72        return $list;
73    }
74}
75

Next, using the script, we pass all these fields, and in the end we can select any day, at any time, from 00:00 PM to 11:30 PM

1<?php
2
3namespace common\models;
4
5use yii\behaviors\TimestampBehavior;
6use yii\db\ActiveRecord;
7use yii\db\Expression;
8
9class WorkHours extends _source_WorkHours
10{
11    public const WEEK_DAY_MON = 'Mon';
12    public const WEEK_DAY_TUE = 'Tue';
13    public const WEEK_DAY_WED = 'Wed';
14    public const WEEK_DAY_THU = 'Thu';
15    public const WEEK_DAY_FRI = 'Fri';
16    public const WEEK_DAY_SAT = 'Sat';
17    public const WEEK_DAY_SUN = 'Sun';
18
19
20    /**
21     * {@inheritdoc}
22     */
23    public function behaviors(): array
24    {
25        return [
26            'timestamp' => [
27                'class'      => TimestampBehavior::class,
28                'attributes' => [
29                    ActiveRecord::EVENT_BEFORE_INSERT => ['created_at'],
30                ],
31                'value'      => new Expression('NOW()'),
32            ],
33        ];
34    }
35
36    public static function weekDays(): array
37    {
38        return [
39            self::WEEK_DAY_MON => 'Monday',
40            self::WEEK_DAY_TUE => 'Tuesday',
41            self::WEEK_DAY_WED => 'Wednesday',
42            self::WEEK_DAY_THU => 'Thursday',
43            self::WEEK_DAY_FRI => 'Friday',
44            self::WEEK_DAY_SAT => 'Saturday',
45            self::WEEK_DAY_SUN => 'Sunday',
46        ];
47    }
48
49    public static function getWeekDay(string $val): string
50    {
51        $ar = self::weekDays();
52
53        return $ar[$val] ?? $val;
54    }
55
56    public static function hoursList(): array
57    {
58        $list = [];
59        for ($i = 0; $i < 24; $i++) {
60            $A = 'AM';
61            $n = $i;
62            if ($i >= 12) {
63                $A = 'PM';
64                $n = $i - 12;
65            }
66
67            $n = $n < 10 ? '0' . $n : $n;
68            $_A = ($i === 12 ? 'AM' : $A);
69            $list[$i . '.00'] = $n . '.00 ' . ($i === 0 ? 'PM' : $_A);
70            $list[$i . '.30'] = $n . '.30 ' . $A;
71        }
72        return $list;
73    }
74}
75$this->registerJsFile('/js/restaurant-reserve.js', ['depends' => [JqueryAsset::class]]);
76$this->registerJs('restaurantReserve.init()');
77
78<a class="btn btn-fourth <?= $restaurantReservationForm->getErrors('date') ? 'btn-error' : '' ?>" id="reservation-date" data-date="<?= $restaurantReservationForm->getDate()
79                   ? $restaurantReservationForm->getDate()->format('m/d/Y') : '' ?>>">
80  <span class="icon br-calender"></span> <span class="js-value">
81                    <?= $restaurantReservationForm->date
82                        ? (new DateTime($restaurantReservationForm->date))->format('d M') : '-- ---' ?>
83                </span>
84</a>
85<a class="btn btn-fourth <?= $restaurantReservationForm->getErrors('time') ? 'btn-error' : '' ?>" id="reservation-time" role="button" data-bs-toggle="dropdown" aria-expanded="false">
86  <span class="icon br-clock"></span> <span class="js-value">
87                    <?= $restaurantReservationForm->time
88                        ? WorkHours::hoursList()[$restaurantReservationForm->time] : '-- : --' ?>
89                </span>
90</a>
91<ul class="dropdown-menu dropdown-menu-height-fixed" aria-labelledby="reservation-time">
92  <?php foreach (WorkHours::hoursList() as $k => $v) { ?>
93    <li>
94      <a class="dropdown-item <?= $restaurantReservationForm->time === $k ? 'active' : ''
95                        ?>" href="#" data-value="<?= $k ?>">
96        <?= $v ?>
97      </a>
98    </li>
99    <?php } ?>
100</ul>
101

Here is the script

1<?php
2
3namespace common\models;
4
5use yii\behaviors\TimestampBehavior;
6use yii\db\ActiveRecord;
7use yii\db\Expression;
8
9class WorkHours extends _source_WorkHours
10{
11    public const WEEK_DAY_MON = 'Mon';
12    public const WEEK_DAY_TUE = 'Tue';
13    public const WEEK_DAY_WED = 'Wed';
14    public const WEEK_DAY_THU = 'Thu';
15    public const WEEK_DAY_FRI = 'Fri';
16    public const WEEK_DAY_SAT = 'Sat';
17    public const WEEK_DAY_SUN = 'Sun';
18
19
20    /**
21     * {@inheritdoc}
22     */
23    public function behaviors(): array
24    {
25        return [
26            'timestamp' => [
27                'class'      => TimestampBehavior::class,
28                'attributes' => [
29                    ActiveRecord::EVENT_BEFORE_INSERT => ['created_at'],
30                ],
31                'value'      => new Expression('NOW()'),
32            ],
33        ];
34    }
35
36    public static function weekDays(): array
37    {
38        return [
39            self::WEEK_DAY_MON => 'Monday',
40            self::WEEK_DAY_TUE => 'Tuesday',
41            self::WEEK_DAY_WED => 'Wednesday',
42            self::WEEK_DAY_THU => 'Thursday',
43            self::WEEK_DAY_FRI => 'Friday',
44            self::WEEK_DAY_SAT => 'Saturday',
45            self::WEEK_DAY_SUN => 'Sunday',
46        ];
47    }
48
49    public static function getWeekDay(string $val): string
50    {
51        $ar = self::weekDays();
52
53        return $ar[$val] ?? $val;
54    }
55
56    public static function hoursList(): array
57    {
58        $list = [];
59        for ($i = 0; $i < 24; $i++) {
60            $A = 'AM';
61            $n = $i;
62            if ($i >= 12) {
63                $A = 'PM';
64                $n = $i - 12;
65            }
66
67            $n = $n < 10 ? '0' . $n : $n;
68            $_A = ($i === 12 ? 'AM' : $A);
69            $list[$i . '.00'] = $n . '.00 ' . ($i === 0 ? 'PM' : $_A);
70            $list[$i . '.30'] = $n . '.30 ' . $A;
71        }
72        return $list;
73    }
74}
75$this->registerJsFile('/js/restaurant-reserve.js', ['depends' => [JqueryAsset::class]]);
76$this->registerJs('restaurantReserve.init()');
77
78<a class="btn btn-fourth <?= $restaurantReservationForm->getErrors('date') ? 'btn-error' : '' ?>" id="reservation-date" data-date="<?= $restaurantReservationForm->getDate()
79                   ? $restaurantReservationForm->getDate()->format('m/d/Y') : '' ?>>">
80  <span class="icon br-calender"></span> <span class="js-value">
81                    <?= $restaurantReservationForm->date
82                        ? (new DateTime($restaurantReservationForm->date))->format('d M') : '-- ---' ?>
83                </span>
84</a>
85<a class="btn btn-fourth <?= $restaurantReservationForm->getErrors('time') ? 'btn-error' : '' ?>" id="reservation-time" role="button" data-bs-toggle="dropdown" aria-expanded="false">
86  <span class="icon br-clock"></span> <span class="js-value">
87                    <?= $restaurantReservationForm->time
88                        ? WorkHours::hoursList()[$restaurantReservationForm->time] : '-- : --' ?>
89                </span>
90</a>
91<ul class="dropdown-menu dropdown-menu-height-fixed" aria-labelledby="reservation-time">
92  <?php foreach (WorkHours::hoursList() as $k => $v) { ?>
93    <li>
94      <a class="dropdown-item <?= $restaurantReservationForm->time === $k ? 'active' : ''
95                        ?>" href="#" data-value="<?= $k ?>">
96        <?= $v ?>
97      </a>
98    </li>
99    <?php } ?>
100</ul>
101let restaurantReserve = {
102    init: function () {
103        let _self = this;
104
105        $('#reservation-date').datepicker({startDate: '+0d'}).on('changeDate', function (e) {
106            const arDate = e.date.toString().split(' ');
107            let input = $('[name="RestaurantReservationForm[date]"]');
108            input.val(arDate[3] + '-' + (e.date.getMonth() + 1) + '-' + arDate[2]);
109            _self.unSetError(input);
110            $('#reservation-date .js-value').text(arDate[2] + ' ' + arDate[1]);
111        });
112
113        $('[aria-labelledby="reservation-time"] li a').click(function () {
114            $(this).closest('ul').find('a').removeClass('active');
115            $(this).addClass('active');
116            let input = $('[name="RestaurantReservationForm[time]"]');
117            input.val($(this).data('value'));
118            _self.unSetError(input);
119            $('#reservation-time .js-value').text($(this).text());
120        });
121
122        $('[aria-labelledby="reservation-person"] li a').click(function () {
123            $(this).closest('ul').find('a').removeClass('active');
124            $(this).addClass('active');
125            let input = $('[name="RestaurantReservationForm[personCount]"]');
126            input.val($(this).data('value'));
127            _self.unSetError(input);
128            $('#reservation-person .js-value').text($(this).data('value'));
129        });
130    },
131    setError: function (ob) {
132        $('#' + ob.data('btnId')).addClass('btn-error');
133    },
134    unSetError: function (ob) {
135        $('#' + ob.data('btnId')).removeClass('btn-error');
136    }
137}
138

I have different establishments and each establishment has its own working hours. And I need to have a choice of time for a particular institution on a particular day. Let's say one establishment on Monday has a working time from 9:30 AM to 2.30 PM, as a result, the select should have a choice of time only in this interval.

What am I trying to do

To begin with, pass data from the database to the init function via json

1<?php
2
3namespace common\models;
4
5use yii\behaviors\TimestampBehavior;
6use yii\db\ActiveRecord;
7use yii\db\Expression;
8
9class WorkHours extends _source_WorkHours
10{
11    public const WEEK_DAY_MON = 'Mon';
12    public const WEEK_DAY_TUE = 'Tue';
13    public const WEEK_DAY_WED = 'Wed';
14    public const WEEK_DAY_THU = 'Thu';
15    public const WEEK_DAY_FRI = 'Fri';
16    public const WEEK_DAY_SAT = 'Sat';
17    public const WEEK_DAY_SUN = 'Sun';
18
19
20    /**
21     * {@inheritdoc}
22     */
23    public function behaviors(): array
24    {
25        return [
26            'timestamp' => [
27                'class'      => TimestampBehavior::class,
28                'attributes' => [
29                    ActiveRecord::EVENT_BEFORE_INSERT => ['created_at'],
30                ],
31                'value'      => new Expression('NOW()'),
32            ],
33        ];
34    }
35
36    public static function weekDays(): array
37    {
38        return [
39            self::WEEK_DAY_MON => 'Monday',
40            self::WEEK_DAY_TUE => 'Tuesday',
41            self::WEEK_DAY_WED => 'Wednesday',
42            self::WEEK_DAY_THU => 'Thursday',
43            self::WEEK_DAY_FRI => 'Friday',
44            self::WEEK_DAY_SAT => 'Saturday',
45            self::WEEK_DAY_SUN => 'Sunday',
46        ];
47    }
48
49    public static function getWeekDay(string $val): string
50    {
51        $ar = self::weekDays();
52
53        return $ar[$val] ?? $val;
54    }
55
56    public static function hoursList(): array
57    {
58        $list = [];
59        for ($i = 0; $i < 24; $i++) {
60            $A = 'AM';
61            $n = $i;
62            if ($i >= 12) {
63                $A = 'PM';
64                $n = $i - 12;
65            }
66
67            $n = $n < 10 ? '0' . $n : $n;
68            $_A = ($i === 12 ? 'AM' : $A);
69            $list[$i . '.00'] = $n . '.00 ' . ($i === 0 ? 'PM' : $_A);
70            $list[$i . '.30'] = $n . '.30 ' . $A;
71        }
72        return $list;
73    }
74}
75$this->registerJsFile('/js/restaurant-reserve.js', ['depends' => [JqueryAsset::class]]);
76$this->registerJs('restaurantReserve.init()');
77
78<a class="btn btn-fourth <?= $restaurantReservationForm->getErrors('date') ? 'btn-error' : '' ?>" id="reservation-date" data-date="<?= $restaurantReservationForm->getDate()
79                   ? $restaurantReservationForm->getDate()->format('m/d/Y') : '' ?>>">
80  <span class="icon br-calender"></span> <span class="js-value">
81                    <?= $restaurantReservationForm->date
82                        ? (new DateTime($restaurantReservationForm->date))->format('d M') : '-- ---' ?>
83                </span>
84</a>
85<a class="btn btn-fourth <?= $restaurantReservationForm->getErrors('time') ? 'btn-error' : '' ?>" id="reservation-time" role="button" data-bs-toggle="dropdown" aria-expanded="false">
86  <span class="icon br-clock"></span> <span class="js-value">
87                    <?= $restaurantReservationForm->time
88                        ? WorkHours::hoursList()[$restaurantReservationForm->time] : '-- : --' ?>
89                </span>
90</a>
91<ul class="dropdown-menu dropdown-menu-height-fixed" aria-labelledby="reservation-time">
92  <?php foreach (WorkHours::hoursList() as $k => $v) { ?>
93    <li>
94      <a class="dropdown-item <?= $restaurantReservationForm->time === $k ? 'active' : ''
95                        ?>" href="#" data-value="<?= $k ?>">
96        <?= $v ?>
97      </a>
98    </li>
99    <?php } ?>
100</ul>
101let restaurantReserve = {
102    init: function () {
103        let _self = this;
104
105        $('#reservation-date').datepicker({startDate: '+0d'}).on('changeDate', function (e) {
106            const arDate = e.date.toString().split(' ');
107            let input = $('[name="RestaurantReservationForm[date]"]');
108            input.val(arDate[3] + '-' + (e.date.getMonth() + 1) + '-' + arDate[2]);
109            _self.unSetError(input);
110            $('#reservation-date .js-value').text(arDate[2] + ' ' + arDate[1]);
111        });
112
113        $('[aria-labelledby="reservation-time"] li a').click(function () {
114            $(this).closest('ul').find('a').removeClass('active');
115            $(this).addClass('active');
116            let input = $('[name="RestaurantReservationForm[time]"]');
117            input.val($(this).data('value'));
118            _self.unSetError(input);
119            $('#reservation-time .js-value').text($(this).text());
120        });
121
122        $('[aria-labelledby="reservation-person"] li a').click(function () {
123            $(this).closest('ul').find('a').removeClass('active');
124            $(this).addClass('active');
125            let input = $('[name="RestaurantReservationForm[personCount]"]');
126            input.val($(this).data('value'));
127            _self.unSetError(input);
128            $('#reservation-person .js-value').text($(this).data('value'));
129        });
130    },
131    setError: function (ob) {
132        $('#' + ob.data('btnId')).addClass('btn-error');
133    },
134    unSetError: function (ob) {
135        $('#' + ob.data('btnId')).removeClass('btn-error');
136    }
137}
138$this->registerJs('restaurantReserve.init('. Json::encode($restaurant->workHours) .')');
139

As a result, we pass data to the script in the form of an array with a database [{"id":"1","restaurant_id":"1","day":"Mon","open":"9.30","close":"14.30","created_at":"2022-02-15 05:00:57"}]

Here's the plug, I have the necessary data, it remains only to add the script so that for each day there is a time interval taken from this data

I need another function like

1<?php
2
3namespace common\models;
4
5use yii\behaviors\TimestampBehavior;
6use yii\db\ActiveRecord;
7use yii\db\Expression;
8
9class WorkHours extends _source_WorkHours
10{
11    public const WEEK_DAY_MON = 'Mon';
12    public const WEEK_DAY_TUE = 'Tue';
13    public const WEEK_DAY_WED = 'Wed';
14    public const WEEK_DAY_THU = 'Thu';
15    public const WEEK_DAY_FRI = 'Fri';
16    public const WEEK_DAY_SAT = 'Sat';
17    public const WEEK_DAY_SUN = 'Sun';
18
19
20    /**
21     * {@inheritdoc}
22     */
23    public function behaviors(): array
24    {
25        return [
26            'timestamp' => [
27                'class'      => TimestampBehavior::class,
28                'attributes' => [
29                    ActiveRecord::EVENT_BEFORE_INSERT => ['created_at'],
30                ],
31                'value'      => new Expression('NOW()'),
32            ],
33        ];
34    }
35
36    public static function weekDays(): array
37    {
38        return [
39            self::WEEK_DAY_MON => 'Monday',
40            self::WEEK_DAY_TUE => 'Tuesday',
41            self::WEEK_DAY_WED => 'Wednesday',
42            self::WEEK_DAY_THU => 'Thursday',
43            self::WEEK_DAY_FRI => 'Friday',
44            self::WEEK_DAY_SAT => 'Saturday',
45            self::WEEK_DAY_SUN => 'Sunday',
46        ];
47    }
48
49    public static function getWeekDay(string $val): string
50    {
51        $ar = self::weekDays();
52
53        return $ar[$val] ?? $val;
54    }
55
56    public static function hoursList(): array
57    {
58        $list = [];
59        for ($i = 0; $i < 24; $i++) {
60            $A = 'AM';
61            $n = $i;
62            if ($i >= 12) {
63                $A = 'PM';
64                $n = $i - 12;
65            }
66
67            $n = $n < 10 ? '0' . $n : $n;
68            $_A = ($i === 12 ? 'AM' : $A);
69            $list[$i . '.00'] = $n . '.00 ' . ($i === 0 ? 'PM' : $_A);
70            $list[$i . '.30'] = $n . '.30 ' . $A;
71        }
72        return $list;
73    }
74}
75$this->registerJsFile('/js/restaurant-reserve.js', ['depends' => [JqueryAsset::class]]);
76$this->registerJs('restaurantReserve.init()');
77
78<a class="btn btn-fourth <?= $restaurantReservationForm->getErrors('date') ? 'btn-error' : '' ?>" id="reservation-date" data-date="<?= $restaurantReservationForm->getDate()
79                   ? $restaurantReservationForm->getDate()->format('m/d/Y') : '' ?>>">
80  <span class="icon br-calender"></span> <span class="js-value">
81                    <?= $restaurantReservationForm->date
82                        ? (new DateTime($restaurantReservationForm->date))->format('d M') : '-- ---' ?>
83                </span>
84</a>
85<a class="btn btn-fourth <?= $restaurantReservationForm->getErrors('time') ? 'btn-error' : '' ?>" id="reservation-time" role="button" data-bs-toggle="dropdown" aria-expanded="false">
86  <span class="icon br-clock"></span> <span class="js-value">
87                    <?= $restaurantReservationForm->time
88                        ? WorkHours::hoursList()[$restaurantReservationForm->time] : '-- : --' ?>
89                </span>
90</a>
91<ul class="dropdown-menu dropdown-menu-height-fixed" aria-labelledby="reservation-time">
92  <?php foreach (WorkHours::hoursList() as $k => $v) { ?>
93    <li>
94      <a class="dropdown-item <?= $restaurantReservationForm->time === $k ? 'active' : ''
95                        ?>" href="#" data-value="<?= $k ?>">
96        <?= $v ?>
97      </a>
98    </li>
99    <?php } ?>
100</ul>
101let restaurantReserve = {
102    init: function () {
103        let _self = this;
104
105        $('#reservation-date').datepicker({startDate: '+0d'}).on('changeDate', function (e) {
106            const arDate = e.date.toString().split(' ');
107            let input = $('[name="RestaurantReservationForm[date]"]');
108            input.val(arDate[3] + '-' + (e.date.getMonth() + 1) + '-' + arDate[2]);
109            _self.unSetError(input);
110            $('#reservation-date .js-value').text(arDate[2] + ' ' + arDate[1]);
111        });
112
113        $('[aria-labelledby="reservation-time"] li a').click(function () {
114            $(this).closest('ul').find('a').removeClass('active');
115            $(this).addClass('active');
116            let input = $('[name="RestaurantReservationForm[time]"]');
117            input.val($(this).data('value'));
118            _self.unSetError(input);
119            $('#reservation-time .js-value').text($(this).text());
120        });
121
122        $('[aria-labelledby="reservation-person"] li a').click(function () {
123            $(this).closest('ul').find('a').removeClass('active');
124            $(this).addClass('active');
125            let input = $('[name="RestaurantReservationForm[personCount]"]');
126            input.val($(this).data('value'));
127            _self.unSetError(input);
128            $('#reservation-person .js-value').text($(this).data('value'));
129        });
130    },
131    setError: function (ob) {
132        $('#' + ob.data('btnId')).addClass('btn-error');
133    },
134    unSetError: function (ob) {
135        $('#' + ob.data('btnId')).removeClass('btn-error');
136    }
137}
138$this->registerJs('restaurantReserve.init('. Json::encode($restaurant->workHours) .')');
139restaurantDate: function (e) {
140        ...
141    }
142

But what to do in it, I still do not quite understand

Here is a snippet of how everything should look like, now you can choose any time here, but i need to have a time interval for each day that will be transmitted from json

1<?php
2
3namespace common\models;
4
5use yii\behaviors\TimestampBehavior;
6use yii\db\ActiveRecord;
7use yii\db\Expression;
8
9class WorkHours extends _source_WorkHours
10{
11    public const WEEK_DAY_MON = 'Mon';
12    public const WEEK_DAY_TUE = 'Tue';
13    public const WEEK_DAY_WED = 'Wed';
14    public const WEEK_DAY_THU = 'Thu';
15    public const WEEK_DAY_FRI = 'Fri';
16    public const WEEK_DAY_SAT = 'Sat';
17    public const WEEK_DAY_SUN = 'Sun';
18
19
20    /**
21     * {@inheritdoc}
22     */
23    public function behaviors(): array
24    {
25        return [
26            'timestamp' => [
27                'class'      => TimestampBehavior::class,
28                'attributes' => [
29                    ActiveRecord::EVENT_BEFORE_INSERT => ['created_at'],
30                ],
31                'value'      => new Expression('NOW()'),
32            ],
33        ];
34    }
35
36    public static function weekDays(): array
37    {
38        return [
39            self::WEEK_DAY_MON => 'Monday',
40            self::WEEK_DAY_TUE => 'Tuesday',
41            self::WEEK_DAY_WED => 'Wednesday',
42            self::WEEK_DAY_THU => 'Thursday',
43            self::WEEK_DAY_FRI => 'Friday',
44            self::WEEK_DAY_SAT => 'Saturday',
45            self::WEEK_DAY_SUN => 'Sunday',
46        ];
47    }
48
49    public static function getWeekDay(string $val): string
50    {
51        $ar = self::weekDays();
52
53        return $ar[$val] ?? $val;
54    }
55
56    public static function hoursList(): array
57    {
58        $list = [];
59        for ($i = 0; $i < 24; $i++) {
60            $A = 'AM';
61            $n = $i;
62            if ($i >= 12) {
63                $A = 'PM';
64                $n = $i - 12;
65            }
66
67            $n = $n < 10 ? '0' . $n : $n;
68            $_A = ($i === 12 ? 'AM' : $A);
69            $list[$i . '.00'] = $n . '.00 ' . ($i === 0 ? 'PM' : $_A);
70            $list[$i . '.30'] = $n . '.30 ' . $A;
71        }
72        return $list;
73    }
74}
75$this->registerJsFile('/js/restaurant-reserve.js', ['depends' => [JqueryAsset::class]]);
76$this->registerJs('restaurantReserve.init()');
77
78<a class="btn btn-fourth <?= $restaurantReservationForm->getErrors('date') ? 'btn-error' : '' ?>" id="reservation-date" data-date="<?= $restaurantReservationForm->getDate()
79                   ? $restaurantReservationForm->getDate()->format('m/d/Y') : '' ?>>">
80  <span class="icon br-calender"></span> <span class="js-value">
81                    <?= $restaurantReservationForm->date
82                        ? (new DateTime($restaurantReservationForm->date))->format('d M') : '-- ---' ?>
83                </span>
84</a>
85<a class="btn btn-fourth <?= $restaurantReservationForm->getErrors('time') ? 'btn-error' : '' ?>" id="reservation-time" role="button" data-bs-toggle="dropdown" aria-expanded="false">
86  <span class="icon br-clock"></span> <span class="js-value">
87                    <?= $restaurantReservationForm->time
88                        ? WorkHours::hoursList()[$restaurantReservationForm->time] : '-- : --' ?>
89                </span>
90</a>
91<ul class="dropdown-menu dropdown-menu-height-fixed" aria-labelledby="reservation-time">
92  <?php foreach (WorkHours::hoursList() as $k => $v) { ?>
93    <li>
94      <a class="dropdown-item <?= $restaurantReservationForm->time === $k ? 'active' : ''
95                        ?>" href="#" data-value="<?= $k ?>">
96        <?= $v ?>
97      </a>
98    </li>
99    <?php } ?>
100</ul>
101let restaurantReserve = {
102    init: function () {
103        let _self = this;
104
105        $('#reservation-date').datepicker({startDate: '+0d'}).on('changeDate', function (e) {
106            const arDate = e.date.toString().split(' ');
107            let input = $('[name="RestaurantReservationForm[date]"]');
108            input.val(arDate[3] + '-' + (e.date.getMonth() + 1) + '-' + arDate[2]);
109            _self.unSetError(input);
110            $('#reservation-date .js-value').text(arDate[2] + ' ' + arDate[1]);
111        });
112
113        $('[aria-labelledby="reservation-time"] li a').click(function () {
114            $(this).closest('ul').find('a').removeClass('active');
115            $(this).addClass('active');
116            let input = $('[name="RestaurantReservationForm[time]"]');
117            input.val($(this).data('value'));
118            _self.unSetError(input);
119            $('#reservation-time .js-value').text($(this).text());
120        });
121
122        $('[aria-labelledby="reservation-person"] li a').click(function () {
123            $(this).closest('ul').find('a').removeClass('active');
124            $(this).addClass('active');
125            let input = $('[name="RestaurantReservationForm[personCount]"]');
126            input.val($(this).data('value'));
127            _self.unSetError(input);
128            $('#reservation-person .js-value').text($(this).data('value'));
129        });
130    },
131    setError: function (ob) {
132        $('#' + ob.data('btnId')).addClass('btn-error');
133    },
134    unSetError: function (ob) {
135        $('#' + ob.data('btnId')).removeClass('btn-error');
136    }
137}
138$this->registerJs('restaurantReserve.init('. Json::encode($restaurant->workHours) .')');
139restaurantDate: function (e) {
140        ...
141    }
142let restaurantReserve = {
143    init: function () {
144        let _self = this;
145        
146        $('#reservation-date').datepicker({startDate: '+0d'}).on('changeDate', function (e) {
147            const arDate = e.date.toString().split(' ');
148            let input = $('[name="RestaurantReservationForm[date]"]');
149            input.val(arDate[3] + '-' + (e.date.getMonth() + 1) + '-' + arDate[2]);
150            _self.unSetError(input);
151            $('#reservation-date .js-value').text(arDate[2] + ' ' + arDate[1]);
152        });
153
154        $('[aria-labelledby="reservation-time"] li a').click(function () {
155            $(this).closest('ul').find('a').removeClass('active');
156            $(this).addClass('active');
157            let input = $('[name="RestaurantReservationForm[time]"]');
158            input.val($(this).data('value'));
159            _self.unSetError(input);
160            $('#reservation-time .js-value').text($(this).text());
161        });
162    },
163    setError: function (ob) {
164        $('#' + ob.data('btnId')).addClass('btn-error');
165    },
166    unSetError: function (ob) {
167        $('#' + ob.data('btnId')).removeClass('btn-error');
168    }
169}
170
171restaurantReserve.init();
1<?php
2
3namespace common\models;
4
5use yii\behaviors\TimestampBehavior;
6use yii\db\ActiveRecord;
7use yii\db\Expression;
8
9class WorkHours extends _source_WorkHours
10{
11    public const WEEK_DAY_MON = 'Mon';
12    public const WEEK_DAY_TUE = 'Tue';
13    public const WEEK_DAY_WED = 'Wed';
14    public const WEEK_DAY_THU = 'Thu';
15    public const WEEK_DAY_FRI = 'Fri';
16    public const WEEK_DAY_SAT = 'Sat';
17    public const WEEK_DAY_SUN = 'Sun';
18
19
20    /**
21     * {@inheritdoc}
22     */
23    public function behaviors(): array
24    {
25        return [
26            'timestamp' => [
27                'class'      => TimestampBehavior::class,
28                'attributes' => [
29                    ActiveRecord::EVENT_BEFORE_INSERT => ['created_at'],
30                ],
31                'value'      => new Expression('NOW()'),
32            ],
33        ];
34    }
35
36    public static function weekDays(): array
37    {
38        return [
39            self::WEEK_DAY_MON => 'Monday',
40            self::WEEK_DAY_TUE => 'Tuesday',
41            self::WEEK_DAY_WED => 'Wednesday',
42            self::WEEK_DAY_THU => 'Thursday',
43            self::WEEK_DAY_FRI => 'Friday',
44            self::WEEK_DAY_SAT => 'Saturday',
45            self::WEEK_DAY_SUN => 'Sunday',
46        ];
47    }
48
49    public static function getWeekDay(string $val): string
50    {
51        $ar = self::weekDays();
52
53        return $ar[$val] ?? $val;
54    }
55
56    public static function hoursList(): array
57    {
58        $list = [];
59        for ($i = 0; $i < 24; $i++) {
60            $A = 'AM';
61            $n = $i;
62            if ($i >= 12) {
63                $A = 'PM';
64                $n = $i - 12;
65            }
66
67            $n = $n < 10 ? '0' . $n : $n;
68            $_A = ($i === 12 ? 'AM' : $A);
69            $list[$i . '.00'] = $n . '.00 ' . ($i === 0 ? 'PM' : $_A);
70            $list[$i . '.30'] = $n . '.30 ' . $A;
71        }
72        return $list;
73    }
74}
75$this->registerJsFile('/js/restaurant-reserve.js', ['depends' => [JqueryAsset::class]]);
76$this->registerJs('restaurantReserve.init()');
77
78<a class="btn btn-fourth <?= $restaurantReservationForm->getErrors('date') ? 'btn-error' : '' ?>" id="reservation-date" data-date="<?= $restaurantReservationForm->getDate()
79                   ? $restaurantReservationForm->getDate()->format('m/d/Y') : '' ?>>">
80  <span class="icon br-calender"></span> <span class="js-value">
81                    <?= $restaurantReservationForm->date
82                        ? (new DateTime($restaurantReservationForm->date))->format('d M') : '-- ---' ?>
83                </span>
84</a>
85<a class="btn btn-fourth <?= $restaurantReservationForm->getErrors('time') ? 'btn-error' : '' ?>" id="reservation-time" role="button" data-bs-toggle="dropdown" aria-expanded="false">
86  <span class="icon br-clock"></span> <span class="js-value">
87                    <?= $restaurantReservationForm->time
88                        ? WorkHours::hoursList()[$restaurantReservationForm->time] : '-- : --' ?>
89                </span>
90</a>
91<ul class="dropdown-menu dropdown-menu-height-fixed" aria-labelledby="reservation-time">
92  <?php foreach (WorkHours::hoursList() as $k => $v) { ?>
93    <li>
94      <a class="dropdown-item <?= $restaurantReservationForm->time === $k ? 'active' : ''
95                        ?>" href="#" data-value="<?= $k ?>">
96        <?= $v ?>
97      </a>
98    </li>
99    <?php } ?>
100</ul>
101let restaurantReserve = {
102    init: function () {
103        let _self = this;
104
105        $('#reservation-date').datepicker({startDate: '+0d'}).on('changeDate', function (e) {
106            const arDate = e.date.toString().split(' ');
107            let input = $('[name="RestaurantReservationForm[date]"]');
108            input.val(arDate[3] + '-' + (e.date.getMonth() + 1) + '-' + arDate[2]);
109            _self.unSetError(input);
110            $('#reservation-date .js-value').text(arDate[2] + ' ' + arDate[1]);
111        });
112
113        $('[aria-labelledby="reservation-time"] li a').click(function () {
114            $(this).closest('ul').find('a').removeClass('active');
115            $(this).addClass('active');
116            let input = $('[name="RestaurantReservationForm[time]"]');
117            input.val($(this).data('value'));
118            _self.unSetError(input);
119            $('#reservation-time .js-value').text($(this).text());
120        });
121
122        $('[aria-labelledby="reservation-person"] li a').click(function () {
123            $(this).closest('ul').find('a').removeClass('active');
124            $(this).addClass('active');
125            let input = $('[name="RestaurantReservationForm[personCount]"]');
126            input.val($(this).data('value'));
127            _self.unSetError(input);
128            $('#reservation-person .js-value').text($(this).data('value'));
129        });
130    },
131    setError: function (ob) {
132        $('#' + ob.data('btnId')).addClass('btn-error');
133    },
134    unSetError: function (ob) {
135        $('#' + ob.data('btnId')).removeClass('btn-error');
136    }
137}
138$this->registerJs('restaurantReserve.init('. Json::encode($restaurant->workHours) .')');
139restaurantDate: function (e) {
140        ...
141    }
142let restaurantReserve = {
143    init: function () {
144        let _self = this;
145        
146        $('#reservation-date').datepicker({startDate: '+0d'}).on('changeDate', function (e) {
147            const arDate = e.date.toString().split(' ');
148            let input = $('[name="RestaurantReservationForm[date]"]');
149            input.val(arDate[3] + '-' + (e.date.getMonth() + 1) + '-' + arDate[2]);
150            _self.unSetError(input);
151            $('#reservation-date .js-value').text(arDate[2] + ' ' + arDate[1]);
152        });
153
154        $('[aria-labelledby="reservation-time"] li a').click(function () {
155            $(this).closest('ul').find('a').removeClass('active');
156            $(this).addClass('active');
157            let input = $('[name="RestaurantReservationForm[time]"]');
158            input.val($(this).data('value'));
159            _self.unSetError(input);
160            $('#reservation-time .js-value').text($(this).text());
161        });
162    },
163    setError: function (ob) {
164        $('#' + ob.data('btnId')).addClass('btn-error');
165    },
166    unSetError: function (ob) {
167        $('#' + ob.data('btnId')).removeClass('btn-error');
168    }
169}
170
171restaurantReserve.init();.btn {
172    border: none;
173    border-radius: 8px;
174    height: 40px;
175    padding: 10px 15px;
176    font-weight: 800;
177    font-size: 14px;
178    margin-right: 10px;
179    cursor: pointer;
180}
181
182.btn-fourth {
183    text-decoration: none;
184    background: #e3e5e8;
185    color: #747b8b;
186}
187
188ul.with-out > li:before, .dropdown-menu li:before, ul.whithout > li:before {display:none;}
189
190.dropdown-menu li {padding:0;}
191
192.dropdown-menu-height-fixed {max-height:200px;overflow-y:auto;}
193
194.dropdown-item.active, .dropdown-item:active {background:red;}
195
196.block-shadow {box-shadow:0 2px 8px 0 rgba(32,35,44,0.05);}
197.block-white {background:#fff;border-radius:8px;padding:20px;}
1<?php
2
3namespace common\models;
4
5use yii\behaviors\TimestampBehavior;
6use yii\db\ActiveRecord;
7use yii\db\Expression;
8
9class WorkHours extends _source_WorkHours
10{
11    public const WEEK_DAY_MON = 'Mon';
12    public const WEEK_DAY_TUE = 'Tue';
13    public const WEEK_DAY_WED = 'Wed';
14    public const WEEK_DAY_THU = 'Thu';
15    public const WEEK_DAY_FRI = 'Fri';
16    public const WEEK_DAY_SAT = 'Sat';
17    public const WEEK_DAY_SUN = 'Sun';
18
19
20    /**
21     * {@inheritdoc}
22     */
23    public function behaviors(): array
24    {
25        return [
26            'timestamp' => [
27                'class'      => TimestampBehavior::class,
28                'attributes' => [
29                    ActiveRecord::EVENT_BEFORE_INSERT => ['created_at'],
30                ],
31                'value'      => new Expression('NOW()'),
32            ],
33        ];
34    }
35
36    public static function weekDays(): array
37    {
38        return [
39            self::WEEK_DAY_MON => 'Monday',
40            self::WEEK_DAY_TUE => 'Tuesday',
41            self::WEEK_DAY_WED => 'Wednesday',
42            self::WEEK_DAY_THU => 'Thursday',
43            self::WEEK_DAY_FRI => 'Friday',
44            self::WEEK_DAY_SAT => 'Saturday',
45            self::WEEK_DAY_SUN => 'Sunday',
46        ];
47    }
48
49    public static function getWeekDay(string $val): string
50    {
51        $ar = self::weekDays();
52
53        return $ar[$val] ?? $val;
54    }
55
56    public static function hoursList(): array
57    {
58        $list = [];
59        for ($i = 0; $i < 24; $i++) {
60            $A = 'AM';
61            $n = $i;
62            if ($i >= 12) {
63                $A = 'PM';
64                $n = $i - 12;
65            }
66
67            $n = $n < 10 ? '0' . $n : $n;
68            $_A = ($i === 12 ? 'AM' : $A);
69            $list[$i . '.00'] = $n . '.00 ' . ($i === 0 ? 'PM' : $_A);
70            $list[$i . '.30'] = $n . '.30 ' . $A;
71        }
72        return $list;
73    }
74}
75$this->registerJsFile('/js/restaurant-reserve.js', ['depends' => [JqueryAsset::class]]);
76$this->registerJs('restaurantReserve.init()');
77
78<a class="btn btn-fourth <?= $restaurantReservationForm->getErrors('date') ? 'btn-error' : '' ?>" id="reservation-date" data-date="<?= $restaurantReservationForm->getDate()
79                   ? $restaurantReservationForm->getDate()->format('m/d/Y') : '' ?>>">
80  <span class="icon br-calender"></span> <span class="js-value">
81                    <?= $restaurantReservationForm->date
82                        ? (new DateTime($restaurantReservationForm->date))->format('d M') : '-- ---' ?>
83                </span>
84</a>
85<a class="btn btn-fourth <?= $restaurantReservationForm->getErrors('time') ? 'btn-error' : '' ?>" id="reservation-time" role="button" data-bs-toggle="dropdown" aria-expanded="false">
86  <span class="icon br-clock"></span> <span class="js-value">
87                    <?= $restaurantReservationForm->time
88                        ? WorkHours::hoursList()[$restaurantReservationForm->time] : '-- : --' ?>
89                </span>
90</a>
91<ul class="dropdown-menu dropdown-menu-height-fixed" aria-labelledby="reservation-time">
92  <?php foreach (WorkHours::hoursList() as $k => $v) { ?>
93    <li>
94      <a class="dropdown-item <?= $restaurantReservationForm->time === $k ? 'active' : ''
95                        ?>" href="#" data-value="<?= $k ?>">
96        <?= $v ?>
97      </a>
98    </li>
99    <?php } ?>
100</ul>
101let restaurantReserve = {
102    init: function () {
103        let _self = this;
104
105        $('#reservation-date').datepicker({startDate: '+0d'}).on('changeDate', function (e) {
106            const arDate = e.date.toString().split(' ');
107            let input = $('[name="RestaurantReservationForm[date]"]');
108            input.val(arDate[3] + '-' + (e.date.getMonth() + 1) + '-' + arDate[2]);
109            _self.unSetError(input);
110            $('#reservation-date .js-value').text(arDate[2] + ' ' + arDate[1]);
111        });
112
113        $('[aria-labelledby="reservation-time"] li a').click(function () {
114            $(this).closest('ul').find('a').removeClass('active');
115            $(this).addClass('active');
116            let input = $('[name="RestaurantReservationForm[time]"]');
117            input.val($(this).data('value'));
118            _self.unSetError(input);
119            $('#reservation-time .js-value').text($(this).text());
120        });
121
122        $('[aria-labelledby="reservation-person"] li a').click(function () {
123            $(this).closest('ul').find('a').removeClass('active');
124            $(this).addClass('active');
125            let input = $('[name="RestaurantReservationForm[personCount]"]');
126            input.val($(this).data('value'));
127            _self.unSetError(input);
128            $('#reservation-person .js-value').text($(this).data('value'));
129        });
130    },
131    setError: function (ob) {
132        $('#' + ob.data('btnId')).addClass('btn-error');
133    },
134    unSetError: function (ob) {
135        $('#' + ob.data('btnId')).removeClass('btn-error');
136    }
137}
138$this->registerJs('restaurantReserve.init('. Json::encode($restaurant->workHours) .')');
139restaurantDate: function (e) {
140        ...
141    }
142let restaurantReserve = {
143    init: function () {
144        let _self = this;
145        
146        $('#reservation-date').datepicker({startDate: '+0d'}).on('changeDate', function (e) {
147            const arDate = e.date.toString().split(' ');
148            let input = $('[name="RestaurantReservationForm[date]"]');
149            input.val(arDate[3] + '-' + (e.date.getMonth() + 1) + '-' + arDate[2]);
150            _self.unSetError(input);
151            $('#reservation-date .js-value').text(arDate[2] + ' ' + arDate[1]);
152        });
153
154        $('[aria-labelledby="reservation-time"] li a').click(function () {
155            $(this).closest('ul').find('a').removeClass('active');
156            $(this).addClass('active');
157            let input = $('[name="RestaurantReservationForm[time]"]');
158            input.val($(this).data('value'));
159            _self.unSetError(input);
160            $('#reservation-time .js-value').text($(this).text());
161        });
162    },
163    setError: function (ob) {
164        $('#' + ob.data('btnId')).addClass('btn-error');
165    },
166    unSetError: function (ob) {
167        $('#' + ob.data('btnId')).removeClass('btn-error');
168    }
169}
170
171restaurantReserve.init();.btn {
172    border: none;
173    border-radius: 8px;
174    height: 40px;
175    padding: 10px 15px;
176    font-weight: 800;
177    font-size: 14px;
178    margin-right: 10px;
179    cursor: pointer;
180}
181
182.btn-fourth {
183    text-decoration: none;
184    background: #e3e5e8;
185    color: #747b8b;
186}
187
188ul.with-out > li:before, .dropdown-menu li:before, ul.whithout > li:before {display:none;}
189
190.dropdown-menu li {padding:0;}
191
192.dropdown-menu-height-fixed {max-height:200px;overflow-y:auto;}
193
194.dropdown-item.active, .dropdown-item:active {background:red;}
195
196.block-shadow {box-shadow:0 2px 8px 0 rgba(32,35,44,0.05);}
197.block-white {background:#fff;border-radius:8px;padding:20px;}<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
198<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.9.0/css/bootstrap-datepicker.min.css" rel="stylesheet">
199<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.9.0/js/bootstrap-datepicker.min.js"></script>
200
201<form id="reservation" action="/restaurants/123/" method="post">
202   <div class="block-shadow block-white mb-4">
203        <h5 class="fw-bold mb-3">Reserve a table</h5>
204        <div class="btn-s">
205            <a class="btn btn-fourth "
206               id="reservation-date"
207               data-date=">">
208                <span class="icon br-calender"></span> <span class="js-value">
209                    -- ---                </span>
210            </a>
211            <a class="btn btn-fourth "
212               id="reservation-time" role="button" data-bs-toggle="dropdown" aria-expanded="false">
213                <span class="icon br-clock"></span> <span class="js-value">
214                    -- : --                </span>
215            </a>
216            <ul class="dropdown-menu dropdown-menu-height-fixed" aria-labelledby="reservation-time">
217                                    <li><a class="dropdown-item " href="#" data-value="0.00">00.00 PM</a></li>
218                                    <li><a class="dropdown-item " href="#" data-value="0.30">00.30 AM</a></li>
219                                    <li><a class="dropdown-item " href="#" data-value="1.00">01.00 AM</a></li>
220                                    <li><a class="dropdown-item " href="#" data-value="1.30">01.30 AM</a></li>
221                                    <li><a class="dropdown-item " href="#" data-value="2.00">02.00 AM</a></li>
222                                    <li><a class="dropdown-item " href="#" data-value="2.30">02.30 AM</a></li>
223                                    <li><a class="dropdown-item " href="#" data-value="3.00">03.00 AM</a></li>
224                                    <li><a class="dropdown-item " href="#" data-value="3.30">03.30 AM</a></li>
225                                    <li><a class="dropdown-item " href="#" data-value="4.00">04.00 AM</a></li>
226                                    <li><a class="dropdown-item " href="#" data-value="4.30">04.30 AM</a></li>
227                                    <li><a class="dropdown-item " href="#" data-value="5.00">05.00 AM</a></li>
228                                    <li><a class="dropdown-item " href="#" data-value="5.30">05.30 AM</a></li>
229                                    <li><a class="dropdown-item " href="#" data-value="6.00">06.00 AM</a></li>
230                                    <li><a class="dropdown-item " href="#" data-value="6.30">06.30 AM</a></li>
231                                    <li><a class="dropdown-item " href="#" data-value="7.00">07.00 AM</a></li>
232                                    <li><a class="dropdown-item " href="#" data-value="7.30">07.30 AM</a></li>
233                                    <li><a class="dropdown-item " href="#" data-value="8.00">08.00 AM</a></li>
234                                    <li><a class="dropdown-item " href="#" data-value="8.30">08.30 AM</a></li>
235                                    <li><a class="dropdown-item " href="#" data-value="9.00">09.00 AM</a></li>
236                                    <li><a class="dropdown-item " href="#" data-value="9.30">09.30 AM</a></li>
237                                    <li><a class="dropdown-item " href="#" data-value="10.00">10.00 AM</a></li>
238                                    <li><a class="dropdown-item " href="#" data-value="10.30">10.30 AM</a></li>
239                                    <li><a class="dropdown-item " href="#" data-value="11.00">11.00 AM</a></li>
240                                    <li><a class="dropdown-item " href="#" data-value="11.30">11.30 AM</a></li>
241                                    <li><a class="dropdown-item " href="#" data-value="12.00">00.00 AM</a></li>
242                                    <li><a class="dropdown-item " href="#" data-value="12.30">00.30 PM</a></li>
243                                    <li><a class="dropdown-item " href="#" data-value="13.00">01.00 PM</a></li>
244                                    <li><a class="dropdown-item " href="#" data-value="13.30">01.30 PM</a></li>
245                                    <li><a class="dropdown-item " href="#" data-value="14.00">02.00 PM</a></li>
246                                    <li><a class="dropdown-item " href="#" data-value="14.30">02.30 PM</a></li>
247                                    <li><a class="dropdown-item " href="#" data-value="15.00">03.00 PM</a></li>
248                                    <li><a class="dropdown-item " href="#" data-value="15.30">03.30 PM</a></li>
249                                    <li><a class="dropdown-item " href="#" data-value="16.00">04.00 PM</a></li>
250                                    <li><a class="dropdown-item " href="#" data-value="16.30">04.30 PM</a></li>
251                                    <li><a class="dropdown-item " href="#" data-value="17.00">05.00 PM</a></li>
252                                    <li><a class="dropdown-item " href="#" data-value="17.30">05.30 PM</a></li>
253                                    <li><a class="dropdown-item " href="#" data-value="18.00">06.00 PM</a></li>
254                                    <li><a class="dropdown-item " href="#" data-value="18.30">06.30 PM</a></li>
255                                    <li><a class="dropdown-item " href="#" data-value="19.00">07.00 PM</a></li>
256                                    <li><a class="dropdown-item " href="#" data-value="19.30">07.30 PM</a></li>
257                                    <li><a class="dropdown-item " href="#" data-value="20.00">08.00 PM</a></li>
258                                    <li><a class="dropdown-item " href="#" data-value="20.30">08.30 PM</a></li>
259                                    <li><a class="dropdown-item " href="#" data-value="21.00">09.00 PM</a></li>
260                                    <li><a class="dropdown-item " href="#" data-value="21.30">09.30 PM</a></li>
261                                    <li><a class="dropdown-item " href="#" data-value="22.00">10.00 PM</a></li>
262                                    <li><a class="dropdown-item " href="#" data-value="22.30">10.30 PM</a></li>
263                                    <li><a class="dropdown-item " href="#" data-value="23.00">11.00 PM</a></li>
264                                    <li><a class="dropdown-item " href="#" data-value="23.30">11.30 PM</a></li>
265                            </ul>
266        </div>
267        <div class="form-group field-restaurantreservationform-personcount">
268<input type="hidden" id="restaurantreservationform-personcount" class="form-control" name="RestaurantReservationForm[personCount]" data-btn-id="reservation-person">
269</div>        <div class="form-group field-restaurantreservationform-date required">
270<input type="hidden" id="restaurantreservationform-date" class="form-control" name="RestaurantReservationForm[date]" data-btn-id="reservation-date">
271</div>        <div class="form-group field-restaurantreservationform-time">
272<input type="hidden" id="restaurantreservationform-time" class="form-control" name="RestaurantReservationForm[time]" data-btn-id="reservation-time">
273</div>
1<?php
2
3namespace common\models;
4
5use yii\behaviors\TimestampBehavior;
6use yii\db\ActiveRecord;
7use yii\db\Expression;
8
9class WorkHours extends _source_WorkHours
10{
11    public const WEEK_DAY_MON = 'Mon';
12    public const WEEK_DAY_TUE = 'Tue';
13    public const WEEK_DAY_WED = 'Wed';
14    public const WEEK_DAY_THU = 'Thu';
15    public const WEEK_DAY_FRI = 'Fri';
16    public const WEEK_DAY_SAT = 'Sat';
17    public const WEEK_DAY_SUN = 'Sun';
18
19
20    /**
21     * {@inheritdoc}
22     */
23    public function behaviors(): array
24    {
25        return [
26            'timestamp' => [
27                'class'      => TimestampBehavior::class,
28                'attributes' => [
29                    ActiveRecord::EVENT_BEFORE_INSERT => ['created_at'],
30                ],
31                'value'      => new Expression('NOW()'),
32            ],
33        ];
34    }
35
36    public static function weekDays(): array
37    {
38        return [
39            self::WEEK_DAY_MON => 'Monday',
40            self::WEEK_DAY_TUE => 'Tuesday',
41            self::WEEK_DAY_WED => 'Wednesday',
42            self::WEEK_DAY_THU => 'Thursday',
43            self::WEEK_DAY_FRI => 'Friday',
44            self::WEEK_DAY_SAT => 'Saturday',
45            self::WEEK_DAY_SUN => 'Sunday',
46        ];
47    }
48
49    public static function getWeekDay(string $val): string
50    {
51        $ar = self::weekDays();
52
53        return $ar[$val] ?? $val;
54    }
55
56    public static function hoursList(): array
57    {
58        $list = [];
59        for ($i = 0; $i < 24; $i++) {
60            $A = 'AM';
61            $n = $i;
62            if ($i >= 12) {
63                $A = 'PM';
64                $n = $i - 12;
65            }
66
67            $n = $n < 10 ? '0' . $n : $n;
68            $_A = ($i === 12 ? 'AM' : $A);
69            $list[$i . '.00'] = $n . '.00 ' . ($i === 0 ? 'PM' : $_A);
70            $list[$i . '.30'] = $n . '.30 ' . $A;
71        }
72        return $list;
73    }
74}
75$this->registerJsFile('/js/restaurant-reserve.js', ['depends' => [JqueryAsset::class]]);
76$this->registerJs('restaurantReserve.init()');
77
78<a class="btn btn-fourth <?= $restaurantReservationForm->getErrors('date') ? 'btn-error' : '' ?>" id="reservation-date" data-date="<?= $restaurantReservationForm->getDate()
79                   ? $restaurantReservationForm->getDate()->format('m/d/Y') : '' ?>>">
80  <span class="icon br-calender"></span> <span class="js-value">
81                    <?= $restaurantReservationForm->date
82                        ? (new DateTime($restaurantReservationForm->date))->format('d M') : '-- ---' ?>
83                </span>
84</a>
85<a class="btn btn-fourth <?= $restaurantReservationForm->getErrors('time') ? 'btn-error' : '' ?>" id="reservation-time" role="button" data-bs-toggle="dropdown" aria-expanded="false">
86  <span class="icon br-clock"></span> <span class="js-value">
87                    <?= $restaurantReservationForm->time
88                        ? WorkHours::hoursList()[$restaurantReservationForm->time] : '-- : --' ?>
89                </span>
90</a>
91<ul class="dropdown-menu dropdown-menu-height-fixed" aria-labelledby="reservation-time">
92  <?php foreach (WorkHours::hoursList() as $k => $v) { ?>
93    <li>
94      <a class="dropdown-item <?= $restaurantReservationForm->time === $k ? 'active' : ''
95                        ?>" href="#" data-value="<?= $k ?>">
96        <?= $v ?>
97      </a>
98    </li>
99    <?php } ?>
100</ul>
101let restaurantReserve = {
102    init: function () {
103        let _self = this;
104
105        $('#reservation-date').datepicker({startDate: '+0d'}).on('changeDate', function (e) {
106            const arDate = e.date.toString().split(' ');
107            let input = $('[name="RestaurantReservationForm[date]"]');
108            input.val(arDate[3] + '-' + (e.date.getMonth() + 1) + '-' + arDate[2]);
109            _self.unSetError(input);
110            $('#reservation-date .js-value').text(arDate[2] + ' ' + arDate[1]);
111        });
112
113        $('[aria-labelledby="reservation-time"] li a').click(function () {
114            $(this).closest('ul').find('a').removeClass('active');
115            $(this).addClass('active');
116            let input = $('[name="RestaurantReservationForm[time]"]');
117            input.val($(this).data('value'));
118            _self.unSetError(input);
119            $('#reservation-time .js-value').text($(this).text());
120        });
121
122        $('[aria-labelledby="reservation-person"] li a').click(function () {
123            $(this).closest('ul').find('a').removeClass('active');
124            $(this).addClass('active');
125            let input = $('[name="RestaurantReservationForm[personCount]"]');
126            input.val($(this).data('value'));
127            _self.unSetError(input);
128            $('#reservation-person .js-value').text($(this).data('value'));
129        });
130    },
131    setError: function (ob) {
132        $('#' + ob.data('btnId')).addClass('btn-error');
133    },
134    unSetError: function (ob) {
135        $('#' + ob.data('btnId')).removeClass('btn-error');
136    }
137}
138$this->registerJs('restaurantReserve.init('. Json::encode($restaurant->workHours) .')');
139restaurantDate: function (e) {
140        ...
141    }
142let restaurantReserve = {
143    init: function () {
144        let _self = this;
145        
146        $('#reservation-date').datepicker({startDate: '+0d'}).on('changeDate', function (e) {
147            const arDate = e.date.toString().split(' ');
148            let input = $('[name="RestaurantReservationForm[date]"]');
149            input.val(arDate[3] + '-' + (e.date.getMonth() + 1) + '-' + arDate[2]);
150            _self.unSetError(input);
151            $('#reservation-date .js-value').text(arDate[2] + ' ' + arDate[1]);
152        });
153
154        $('[aria-labelledby="reservation-time"] li a').click(function () {
155            $(this).closest('ul').find('a').removeClass('active');
156            $(this).addClass('active');
157            let input = $('[name="RestaurantReservationForm[time]"]');
158            input.val($(this).data('value'));
159            _self.unSetError(input);
160            $('#reservation-time .js-value').text($(this).text());
161        });
162    },
163    setError: function (ob) {
164        $('#' + ob.data('btnId')).addClass('btn-error');
165    },
166    unSetError: function (ob) {
167        $('#' + ob.data('btnId')).removeClass('btn-error');
168    }
169}
170
171restaurantReserve.init();.btn {
172    border: none;
173    border-radius: 8px;
174    height: 40px;
175    padding: 10px 15px;
176    font-weight: 800;
177    font-size: 14px;
178    margin-right: 10px;
179    cursor: pointer;
180}
181
182.btn-fourth {
183    text-decoration: none;
184    background: #e3e5e8;
185    color: #747b8b;
186}
187
188ul.with-out > li:before, .dropdown-menu li:before, ul.whithout > li:before {display:none;}
189
190.dropdown-menu li {padding:0;}
191
192.dropdown-menu-height-fixed {max-height:200px;overflow-y:auto;}
193
194.dropdown-item.active, .dropdown-item:active {background:red;}
195
196.block-shadow {box-shadow:0 2px 8px 0 rgba(32,35,44,0.05);}
197.block-white {background:#fff;border-radius:8px;padding:20px;}<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
198<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.9.0/css/bootstrap-datepicker.min.css" rel="stylesheet">
199<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.9.0/js/bootstrap-datepicker.min.js"></script>
200
201<form id="reservation" action="/restaurants/123/" method="post">
202   <div class="block-shadow block-white mb-4">
203        <h5 class="fw-bold mb-3">Reserve a table</h5>
204        <div class="btn-s">
205            <a class="btn btn-fourth "
206               id="reservation-date"
207               data-date=">">
208                <span class="icon br-calender"></span> <span class="js-value">
209                    -- ---                </span>
210            </a>
211            <a class="btn btn-fourth "
212               id="reservation-time" role="button" data-bs-toggle="dropdown" aria-expanded="false">
213                <span class="icon br-clock"></span> <span class="js-value">
214                    -- : --                </span>
215            </a>
216            <ul class="dropdown-menu dropdown-menu-height-fixed" aria-labelledby="reservation-time">
217                                    <li><a class="dropdown-item " href="#" data-value="0.00">00.00 PM</a></li>
218                                    <li><a class="dropdown-item " href="#" data-value="0.30">00.30 AM</a></li>
219                                    <li><a class="dropdown-item " href="#" data-value="1.00">01.00 AM</a></li>
220                                    <li><a class="dropdown-item " href="#" data-value="1.30">01.30 AM</a></li>
221                                    <li><a class="dropdown-item " href="#" data-value="2.00">02.00 AM</a></li>
222                                    <li><a class="dropdown-item " href="#" data-value="2.30">02.30 AM</a></li>
223                                    <li><a class="dropdown-item " href="#" data-value="3.00">03.00 AM</a></li>
224                                    <li><a class="dropdown-item " href="#" data-value="3.30">03.30 AM</a></li>
225                                    <li><a class="dropdown-item " href="#" data-value="4.00">04.00 AM</a></li>
226                                    <li><a class="dropdown-item " href="#" data-value="4.30">04.30 AM</a></li>
227                                    <li><a class="dropdown-item " href="#" data-value="5.00">05.00 AM</a></li>
228                                    <li><a class="dropdown-item " href="#" data-value="5.30">05.30 AM</a></li>
229                                    <li><a class="dropdown-item " href="#" data-value="6.00">06.00 AM</a></li>
230                                    <li><a class="dropdown-item " href="#" data-value="6.30">06.30 AM</a></li>
231                                    <li><a class="dropdown-item " href="#" data-value="7.00">07.00 AM</a></li>
232                                    <li><a class="dropdown-item " href="#" data-value="7.30">07.30 AM</a></li>
233                                    <li><a class="dropdown-item " href="#" data-value="8.00">08.00 AM</a></li>
234                                    <li><a class="dropdown-item " href="#" data-value="8.30">08.30 AM</a></li>
235                                    <li><a class="dropdown-item " href="#" data-value="9.00">09.00 AM</a></li>
236                                    <li><a class="dropdown-item " href="#" data-value="9.30">09.30 AM</a></li>
237                                    <li><a class="dropdown-item " href="#" data-value="10.00">10.00 AM</a></li>
238                                    <li><a class="dropdown-item " href="#" data-value="10.30">10.30 AM</a></li>
239                                    <li><a class="dropdown-item " href="#" data-value="11.00">11.00 AM</a></li>
240                                    <li><a class="dropdown-item " href="#" data-value="11.30">11.30 AM</a></li>
241                                    <li><a class="dropdown-item " href="#" data-value="12.00">00.00 AM</a></li>
242                                    <li><a class="dropdown-item " href="#" data-value="12.30">00.30 PM</a></li>
243                                    <li><a class="dropdown-item " href="#" data-value="13.00">01.00 PM</a></li>
244                                    <li><a class="dropdown-item " href="#" data-value="13.30">01.30 PM</a></li>
245                                    <li><a class="dropdown-item " href="#" data-value="14.00">02.00 PM</a></li>
246                                    <li><a class="dropdown-item " href="#" data-value="14.30">02.30 PM</a></li>
247                                    <li><a class="dropdown-item " href="#" data-value="15.00">03.00 PM</a></li>
248                                    <li><a class="dropdown-item " href="#" data-value="15.30">03.30 PM</a></li>
249                                    <li><a class="dropdown-item " href="#" data-value="16.00">04.00 PM</a></li>
250                                    <li><a class="dropdown-item " href="#" data-value="16.30">04.30 PM</a></li>
251                                    <li><a class="dropdown-item " href="#" data-value="17.00">05.00 PM</a></li>
252                                    <li><a class="dropdown-item " href="#" data-value="17.30">05.30 PM</a></li>
253                                    <li><a class="dropdown-item " href="#" data-value="18.00">06.00 PM</a></li>
254                                    <li><a class="dropdown-item " href="#" data-value="18.30">06.30 PM</a></li>
255                                    <li><a class="dropdown-item " href="#" data-value="19.00">07.00 PM</a></li>
256                                    <li><a class="dropdown-item " href="#" data-value="19.30">07.30 PM</a></li>
257                                    <li><a class="dropdown-item " href="#" data-value="20.00">08.00 PM</a></li>
258                                    <li><a class="dropdown-item " href="#" data-value="20.30">08.30 PM</a></li>
259                                    <li><a class="dropdown-item " href="#" data-value="21.00">09.00 PM</a></li>
260                                    <li><a class="dropdown-item " href="#" data-value="21.30">09.30 PM</a></li>
261                                    <li><a class="dropdown-item " href="#" data-value="22.00">10.00 PM</a></li>
262                                    <li><a class="dropdown-item " href="#" data-value="22.30">10.30 PM</a></li>
263                                    <li><a class="dropdown-item " href="#" data-value="23.00">11.00 PM</a></li>
264                                    <li><a class="dropdown-item " href="#" data-value="23.30">11.30 PM</a></li>
265                            </ul>
266        </div>
267        <div class="form-group field-restaurantreservationform-personcount">
268<input type="hidden" id="restaurantreservationform-personcount" class="form-control" name="RestaurantReservationForm[personCount]" data-btn-id="reservation-person">
269</div>        <div class="form-group field-restaurantreservationform-date required">
270<input type="hidden" id="restaurantreservationform-date" class="form-control" name="RestaurantReservationForm[date]" data-btn-id="reservation-date">
271</div>        <div class="form-group field-restaurantreservationform-time">
272<input type="hidden" id="restaurantreservationform-time" class="form-control" name="RestaurantReservationForm[time]" data-btn-id="reservation-time">
273</div>[{"id":86,"restaurant_id":1,"day":"Mon","open":"9.30","close":"14.30","created_at":"2022-02-22 10:56:15"},{"id":87,"restaurant_id":1,"day":"Tue","open":"3.00","close":"21.00","created_at":"2022-02-22 10:56:15"},{"id":88,"restaurant_id":1,"day":"Wed","open":"4.30","close":"6.30","created_at":"2022-02-22 10:56:15"},{"id":89,"restaurant_id":1,"day":"Thu","open":"2.30","close":"7.00","created_at":"2022-02-22 10:56:15"},{"id":90,"restaurant_id":1,"day":"Fri","open":"3.00","close":"22.00","created_at":"2022-02-22 10:56:15"},{"id":91,"restaurant_id":1,"day":"Sat","open":"1.30","close":"4.30","created_at":"2022-02-22 10:56:15"},{"id":92,"restaurant_id":1,"day":"Sun","open":"3.00","close":"20.30","created_at":"2022-02-22 10:56:15"}]
274
1<?php
2
3namespace common\models;
4
5use yii\behaviors\TimestampBehavior;
6use yii\db\ActiveRecord;
7use yii\db\Expression;
8
9class WorkHours extends _source_WorkHours
10{
11    public const WEEK_DAY_MON = 'Mon';
12    public const WEEK_DAY_TUE = 'Tue';
13    public const WEEK_DAY_WED = 'Wed';
14    public const WEEK_DAY_THU = 'Thu';
15    public const WEEK_DAY_FRI = 'Fri';
16    public const WEEK_DAY_SAT = 'Sat';
17    public const WEEK_DAY_SUN = 'Sun';
18
19
20    /**
21     * {@inheritdoc}
22     */
23    public function behaviors(): array
24    {
25        return [
26            'timestamp' => [
27                'class'      => TimestampBehavior::class,
28                'attributes' => [
29                    ActiveRecord::EVENT_BEFORE_INSERT => ['created_at'],
30                ],
31                'value'      => new Expression('NOW()'),
32            ],
33        ];
34    }
35
36    public static function weekDays(): array
37    {
38        return [
39            self::WEEK_DAY_MON => 'Monday',
40            self::WEEK_DAY_TUE => 'Tuesday',
41            self::WEEK_DAY_WED => 'Wednesday',
42            self::WEEK_DAY_THU => 'Thursday',
43            self::WEEK_DAY_FRI => 'Friday',
44            self::WEEK_DAY_SAT => 'Saturday',
45            self::WEEK_DAY_SUN => 'Sunday',
46        ];
47    }
48
49    public static function getWeekDay(string $val): string
50    {
51        $ar = self::weekDays();
52
53        return $ar[$val] ?? $val;
54    }
55
56    public static function hoursList(): array
57    {
58        $list = [];
59        for ($i = 0; $i < 24; $i++) {
60            $A = 'AM';
61            $n = $i;
62            if ($i >= 12) {
63                $A = 'PM';
64                $n = $i - 12;
65            }
66
67            $n = $n < 10 ? '0' . $n : $n;
68            $_A = ($i === 12 ? 'AM' : $A);
69            $list[$i . '.00'] = $n . '.00 ' . ($i === 0 ? 'PM' : $_A);
70            $list[$i . '.30'] = $n . '.30 ' . $A;
71        }
72        return $list;
73    }
74}
75$this->registerJsFile('/js/restaurant-reserve.js', ['depends' => [JqueryAsset::class]]);
76$this->registerJs('restaurantReserve.init()');
77
78<a class="btn btn-fourth <?= $restaurantReservationForm->getErrors('date') ? 'btn-error' : '' ?>" id="reservation-date" data-date="<?= $restaurantReservationForm->getDate()
79                   ? $restaurantReservationForm->getDate()->format('m/d/Y') : '' ?>>">
80  <span class="icon br-calender"></span> <span class="js-value">
81                    <?= $restaurantReservationForm->date
82                        ? (new DateTime($restaurantReservationForm->date))->format('d M') : '-- ---' ?>
83                </span>
84</a>
85<a class="btn btn-fourth <?= $restaurantReservationForm->getErrors('time') ? 'btn-error' : '' ?>" id="reservation-time" role="button" data-bs-toggle="dropdown" aria-expanded="false">
86  <span class="icon br-clock"></span> <span class="js-value">
87                    <?= $restaurantReservationForm->time
88                        ? WorkHours::hoursList()[$restaurantReservationForm->time] : '-- : --' ?>
89                </span>
90</a>
91<ul class="dropdown-menu dropdown-menu-height-fixed" aria-labelledby="reservation-time">
92  <?php foreach (WorkHours::hoursList() as $k => $v) { ?>
93    <li>
94      <a class="dropdown-item <?= $restaurantReservationForm->time === $k ? 'active' : ''
95                        ?>" href="#" data-value="<?= $k ?>">
96        <?= $v ?>
97      </a>
98    </li>
99    <?php } ?>
100</ul>
101let restaurantReserve = {
102    init: function () {
103        let _self = this;
104
105        $('#reservation-date').datepicker({startDate: '+0d'}).on('changeDate', function (e) {
106            const arDate = e.date.toString().split(' ');
107            let input = $('[name="RestaurantReservationForm[date]"]');
108            input.val(arDate[3] + '-' + (e.date.getMonth() + 1) + '-' + arDate[2]);
109            _self.unSetError(input);
110            $('#reservation-date .js-value').text(arDate[2] + ' ' + arDate[1]);
111        });
112
113        $('[aria-labelledby="reservation-time"] li a').click(function () {
114            $(this).closest('ul').find('a').removeClass('active');
115            $(this).addClass('active');
116            let input = $('[name="RestaurantReservationForm[time]"]');
117            input.val($(this).data('value'));
118            _self.unSetError(input);
119            $('#reservation-time .js-value').text($(this).text());
120        });
121
122        $('[aria-labelledby="reservation-person"] li a').click(function () {
123            $(this).closest('ul').find('a').removeClass('active');
124            $(this).addClass('active');
125            let input = $('[name="RestaurantReservationForm[personCount]"]');
126            input.val($(this).data('value'));
127            _self.unSetError(input);
128            $('#reservation-person .js-value').text($(this).data('value'));
129        });
130    },
131    setError: function (ob) {
132        $('#' + ob.data('btnId')).addClass('btn-error');
133    },
134    unSetError: function (ob) {
135        $('#' + ob.data('btnId')).removeClass('btn-error');
136    }
137}
138$this->registerJs('restaurantReserve.init('. Json::encode($restaurant->workHours) .')');
139restaurantDate: function (e) {
140        ...
141    }
142let restaurantReserve = {
143    init: function () {
144        let _self = this;
145        
146        $('#reservation-date').datepicker({startDate: '+0d'}).on('changeDate', function (e) {
147            const arDate = e.date.toString().split(' ');
148            let input = $('[name="RestaurantReservationForm[date]"]');
149            input.val(arDate[3] + '-' + (e.date.getMonth() + 1) + '-' + arDate[2]);
150            _self.unSetError(input);
151            $('#reservation-date .js-value').text(arDate[2] + ' ' + arDate[1]);
152        });
153
154        $('[aria-labelledby="reservation-time"] li a').click(function () {
155            $(this).closest('ul').find('a').removeClass('active');
156            $(this).addClass('active');
157            let input = $('[name="RestaurantReservationForm[time]"]');
158            input.val($(this).data('value'));
159            _self.unSetError(input);