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
by Bigkoo java
12799 Apache-2.0
This is a picker view for android , support linkage effect, timepicker and optionspicker.(时间选择器、省市区三级联动)
by airbnb javascript
11488 MIT
An easily internationalizable, mobile-friendly datepicker library for the web
by ng-bootstrap typescript
7904 MIT
Angular powered Bootstrap
by amsul javascript
7749 MIT
The mobile-friendly, responsive, and lightweight jQuery date & time input picker.
by Hacker0x01 javascript
6462 MIT
A simple and reusable datepicker component for React
by valor-software typescript
5363 MIT
Fast and reliable Bootstrap widgets in Angular (supports Ivy engine)
by gzu-liyujiang java
5358 NOASSERTION
安卓选择器类库,包括日期及时间选择器(可用于出生日期、营业时间等)、单项选择器(可用于性别、民族、职业、学历、星座等)、二三级联动选择器(可用于车牌号、基金定投日期等)、城市地址选择器(分省级、地市级及区县级)、数字选择器(可用于年龄、身高、体重、温度等)、日历选日期择器(可用于酒店及机票预定日期)、颜色选择器、文件及目录选择器、图片选择器等……WheelPicker/DatePicker/TimePicker/OptionPicker/NumberPicker/LinkagePicker/AddressPicker/CarPlatePicker/CalendarPicker/ColorPicker/FilePicker/ImagePicker etc.
by gpbl typescript
4465 MIT
Date picker component for React.
by clauderic javascript
3776 MIT
✨ Infinite scrolling date-picker built with React, with localization, range selection, themes, keyboard support, and more.
Trending New libraries in Datepicker
by loperSeven kotlin
644
:star::tada:一个高颜值日期时间选择器;极简API,内置弹窗,支持农历日期显示,可动态配置样式及主题,选择器支持完全自定义UI。
by MattLLLLL swift
378 MIT
Quick and easy date picker.
by li-xiaojun java
133
XPopup扩展功能库,基于XPopup强大的弹窗能力和PickerView的选择器逻辑,封装了时间选择器弹窗和城市选择器弹窗。
by shahabyazdi javascript
109 MIT
a simple React datepicker component for working with gregorian, persian, arabic and indian calendars
by shantanu561993 go
96
C# Wrapper around Chisel from https://github.com/jpillora/chisel
by persian-tools typescript
80 MIT
Modern React Persian Mobile Date and Time picker
by jumodada typescript
64 MIT
A PC Datepicker with only 9KB
by MohamadKh75 javascript
53 MIT
📅 React Native Jalali DatePicker component for both Android and iOS ✨
by Shmulik-Kravitz typescript
35 GPL-3.0
React jewish datepicker
Top Authors in Datepicker
1
3 Libraries
700
2
3 Libraries
838
3
2 Libraries
5
4
2 Libraries
34
5
2 Libraries
7
6
2 Libraries
8
7
2 Libraries
142
8
2 Libraries
340
9
2 Libraries
8
10
2 Libraries
93
1
3 Libraries
700
2
3 Libraries
838
3
2 Libraries
5
4
2 Libraries
34
5
2 Libraries
7
6
2 Libraries
8
7
2 Libraries
142
8
2 Libraries
340
9
2 Libraries
8
10
2 Libraries
93
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:48I 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.
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:00You 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
QUESTION
The unauthenticated git protocol on port 9418 is no longer supported
Asked 2022-Mar-27 at 13:23I 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:01First, 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 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).
QUESTION
How to change the date picker from spinner to calendar dialogue in Android Kotlin
Asked 2022-Mar-16 at 10:31How 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
ANSWER
Answered 2022-Mar-16 at 10:31Follow 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
QUESTION
Use selected element when selector allow for multiple options
Asked 2022-Mar-08 at 00:34Sorry 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:42Use 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
QUESTION
Dynamic form returns the same value for the first and second input
Asked 2022-Feb-25 at 09:47I'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.
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.
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.
But the rest (third, fourth, and so on) forms are unique as seen in the screenshot below. This is the condition I want.
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:
- Click the "Add Delivery" button twice. So there will be 3 delivery point forms.
- 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:40You 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
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
QUESTION
Pass data from the model to js for a specific day and time
Asked 2022-Feb-23 at 16:12I 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);
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[{"id":107,"restaurant_id":3,"day":"Mon","open":"1.30","close":"19.00","created_at":"2022-02-22 10:58:59"},{"id":108,"restaurant_id":3,"day":"Tue","open":"5.30","close":"8.00","created_at":"2022-02-22 10:58:59"},{"id":109,"restaurant_id":3,"day":"Wed","open":"3.00","close":"20.30","created_at":"2022-02-22 10:58:59"},{"id":110,"restaurant_id":3,"day":"Thu","open":"1.00","close":"12.30","created_at":"2022-02-22 10:58:59"},{"id":111,"restaurant_id":3,"day":"Fri","open":"2.30","close":"12.30","created_at":"2022-02-22 10:58:59"},{"id":112,"restaurant_id":3,"day":"Sat","open":"4.00","close":"22.00","created_at":"2022-02-22 10:58:59"},{"id":113,"restaurant_id":3,"day":"Sun","open":"4.00","close":"22.30","created_at":"2022-02-22 10:58:59"}]
275
ANSWER
Answered 2022-Feb-23 at 16:12Since your code is not a runnable snippet to reproduce the behavior, I will refrain from providing a full solution and, instead, I provide the means to solve the issue. Your JSON of
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[{"id":107,"restaurant_id":3,"day":"Mon","open":"1.30","close":"19.00","created_at":"2022-02-22 10:58:59"},{"id":108,"restaurant_id":3,"day":"Tue","open":"5.30","close":"8.00","created_at":"2022-02-22 10:58:59"},{"id":109,"restaurant_id":3,"day":"Wed","open":"3.00","close":"20.30","created_at":"2022-02-22 10:58:59"},{"id":110,"restaurant_id":3,"day":"Thu","open":"1.00","close":"12.30","created_at":"2022-02-22 10:58:59"},{"id":111,"restaurant_id":3,"day":"Fri","open":"2.30","close":"12.30","created_at":"2022-02-22 10:58:59"},{"id":112,"restaurant_id":3,"day":"Sat","open":"4.00","close":"22.00","created_at":"2022-02-22 10:58:59"},{"id":113,"restaurant_id":3,"day":"Sun","open":"4.00","close":"22.30","created_at":"2022-02-22 10:58:59"}]
275[{"id":"1","restaurant_id":"1","day":"Mon","open":"9.30","close":"14.30","created_at":"2022-02-15 05:00:57"}]
276
has a restaurant_id
and a day
. So, let's define a function that finds all hours for all days for a restaurant:
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[{"id":107,"restaurant_id":3,"day":"Mon","open":"1.30","close":"19.00","created_at":"2022-02-22 10:58:59"},{"id":108,"restaurant_id":3,"day":"Tue","open":"5.30","close":"8.00","created_at":"2022-02-22 10:58:59"},{"id":109,"restaurant_id":3,"day":"Wed","open":"3.00","close":"20.30","created_at":"2022-02-22 10:58:59"},{"id":110,"restaurant_id":3,"day":"Thu","open":"1.00","close":"12.30","created_at":"2022-02-22 10:58:59"},{"id":111,"restaurant_id":3,"day":"Fri","open":"2.30","close":"12.30","created_at":"2022-02-22 10:58:59"},{"id":112,"restaurant_id":3,"day":"Sat","open":"4.00","close":"22.00","created_at":"2022-02-22 10:58:59"},{"id":113,"restaurant_id":3,"day":"Sun","open":"4.00","close":"22.30","created_at":"2022-02-22 10:58:59"}]
275[{"id":"1","restaurant_id":"1","day":"Mon","open":"9.30","close":"14.30","created_at":"2022-02-15 05:00:57"}]
276function getWorkHours(json, restaurant_id) {
277 return json.filter(item => item.restaurant_id === restaurant_id);
278}
279
And this is how you can find the work hours of a day for a restaurant:
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[{"id":107,"restaurant_id":3,"day":"Mon","open":"1.30","close":"19.00","created_at":"2022-02-22 10:58:59"},{"id":108,"restaurant_id":3,"day":"Tue","open":"5.30","close":"8.00","created_at":"2022-02-22 10:58:59"},{"id":109,"restaurant_id":3,"day":"Wed","open":"3.00","close":"20.30","created_at":"2022-02-22 10:58:59"},{"id":110,"restaurant_id":3,"day":"Thu","open":"1.00","close":"12.30","created_at":"2022-02-22 10:58:59"},{"id":111,"restaurant_id":3,"day":"Fri","open":"2.30","close":"12.30","created_at":"2022-02-22 10:58:59"},{"id":112,"restaurant_id":3,"day":"Sat","open":"4.00","close":"22.00","created_at":"2022-02-22 10:58:59"},{"id":113,"restaurant_id":3,"day":"Sun","open":"4.00","close":"22.30","created_at":"2022-02-22 10:58:59"}]
275[{"id":"1","restaurant_id":"1","day":"Mon","open":"9.30","close":"14.30","created_at":"2022-02-15 05:00:57"}]
276function getWorkHours(json, restaurant_id) {
277 return json.filter(item => item.restaurant_id === restaurant_id);
278}
279function getWorkHoursForDay(json, restaurant_id, day) {
280 return getWorkHours(json, restaurant_id).filter(item => item.day === day);
281}
282
Using these functions you can get the data you need. Based on that data you can fill your HTML the way you need. If you need more information, then please provide a minimal reproducible example of your problem, a JSON input, your current HTML and the HTML you desire based on the JSON input. Then I can apply this for your structure. But, in order to do so, I need to have much more information.
EDIT
Based on the discussion we had in the comment section I have received enough information to solve the issue:
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[{"id":107,"restaurant_id":3,"day":"Mon","open":"1.30","close":"19.00","created_at":"2022-02-22 10:58:59"},{"id":108,"restaurant_id":3,"day":"Tue","open":"5.30","close":"8.00","created_at":"2022-02-22 10:58:59"},{"id":109,"restaurant_id":3,"day":"Wed","open":"3.00","close":"20.30","created_at":"2022-02-22 10:58:59"},{"id":110,"restaurant_id":3,"day":"Thu","open":"1.00","close":"12.30","created_at":"2022-02-22 10:58:59"},{"id":111,"restaurant_id":3,"day":"Fri","open":"2.30","close":"12.30","created_at":"2022-02-22 10:58:59"},{"id":112,"restaurant_id":3,"day":"Sat","open":"4.00","close":"22.00","created_at":"2022-02-22 10:58:59"},{"id":113,"restaurant_id":3,"day":"Sun","open":"4.00","close":"22.30","created_at":"2022-02-22 10:58:59"}]
275[{"id":"1","restaurant_id":"1","day":"Mon","open":"9.30","close":"14.30","created_at":"2022-02-15 05:00:57"}]
276function getWorkHours(json, restaurant_id) {
277 return json.filter(item => item.restaurant_id === restaurant_id);
278}
279function getWorkHoursForDay(json, restaurant_id, day) {
280 return getWorkHours(json, restaurant_id).filter(item => item.day === day);
281}
282let restaurantReserve = {
283 init: function () {
284 let _self = this;
285
286 $('#reservation-date').datepicker({startDate: '+0d'}).on('changeDate', function (e) {
287 const arDate = e.date.toString().split(' ');
288 let input = $('[name="RestaurantReservationForm[date]"]');
289 input.val(arDate[3] + '-' + (e.date.getMonth() + 1) + '-' + arDate[2]);
290 _self.unSetError(input);
291 $('#reservation-date .js-value').text(arDate[2] + ' ' + arDate[1]);
292 });
293
294 $('[aria-labelledby="reservation-time"] li a').click(function () {
295 $(this).closest('ul').find('a').removeClass('active');
296 $(this).addClass('active');
297 let input = $('[name="RestaurantReservationForm[time]"]');
298 input.val($(this).data('value'));
299 _self.unSetError(input);
300 $('#reservation-time .js-value').text($(this).text());
301 });
302 },
303 setError: function (ob) {
304 $('#' + ob.data('btnId')).addClass('btn-error');
305 },
306 unSetError: function (ob) {
307 $('#' + ob.data('btnId')).removeClass('btn-error');
308 }
309 }
310
311 restaurantReserve.init();
312
313 let json = [{"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":91,"restaurant_id":1,"day":"Sat","open":"0","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"}, {"id":107,"restaurant_id":3,"day":"Mon","open":"1.30","close":"19.00","created_at":"2022-02-22 10:58:59"},{"id":108,"restaurant_id":3,"day":"Tue","open":"5.30","close":"8.00","created_at":"2022-02-22 10:58:59"},{"id":109,"restaurant_id":3,"day":"Wed","open":"3.00","close":"20.30","created_at":"2022-02-22 10:58:59"},{"id":110,"restaurant_id":3,"day":"Thu","open":"1.00","close":"12.30","created_at":"2022-02-22 10:58:59"},{"id":111,"restaurant_id":3,"day":"Fri","open":"2.30","close":"12.30","created_at":"2022-02-22 10:58:59"},{"id":112,"restaurant_id":3,"day":"Sat","open":"4.00","close":"22.00","created_at":"2022-02-22 10:58:59"},{"id":113,"restaurant_id":3,"day":"Sun","open":"4.00","close":"22.30","created_at":"2022-02-22 10:58:59"}];
314
315 function getWorkHours(json, restaurant_id) {
316 return json.filter(item => item.restaurant_id == restaurant_id);
317 }
318
319 function getWorkHoursForDay(json, restaurant_id, day) {
320 return getWorkHours(json, restaurant_id).filter(item => item.day === day)[0];
321 }
322
323 function filterTimes() {
324 let restaurantID = document.getElementById("restaurantid").value;
325 let dayofweek = document.getElementById("dayofweek").value;
326 if ((["1", "3"].indexOf(restaurantID) >= 0) && ((["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"].indexOf(dayofweek)) >= 0)) {
327 let workHours = getWorkHoursForDay(json, restaurantID, dayofweek);
328 let items = document.querySelectorAll(".dropdown-menu.dropdown-menu-height-fixed li a");
329 for (let item of items) {
330 let itemValueParts = item.innerText.split(" ");
331 itemValue = parseFloat(itemValueParts[0]) + (((itemValueParts[1] === "PM") && (itemValueParts[0] !== "00.00")) ? 12 : 0);
332 item.parentNode.classList[((itemValue < parseFloat(workHours.open)) || (itemValue > parseFloat(workHours.close)) ? "add" : "remove")]("invisible");
333 }
334 }
335 }
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[{"id":107,"restaurant_id":3,"day":"Mon","open":"1.30","close":"19.00","created_at":"2022-02-22 10:58:59"},{"id":108,"restaurant_id":3,"day":"Tue","open":"5.30","close":"8.00","created_at":"2022-02-22 10:58:59"},{"id":109,"restaurant_id":3,"day":"Wed","open":"3.00","close":"20.30","created_at":"2022-02-22 10:58:59"},{"id":110,"restaurant_id":3,"day":"Thu","open":"1.00","close":"12.30","created_at":"2022-02-22 10:58:59"},{"id":111,"restaurant_id":3,"day":"Fri","open":"2.30","close":"12.30","created_at":"2022-02-22 10:58:59"},{"id":112,"restaurant_id":3,"day":"Sat","open":"4.00","close":"22.00","created_at":"2022-02-22 10:58:59"},{"id":113,"restaurant_id":3,"day":"Sun","open":"4.00","close":"22.30","created_at":"2022-02-22 10:58:59"}]
275[{"id":"1","restaurant_id":"1","day":"Mon","open":"9.30","close":"14.30","created_at":"2022-02-15 05:00:57"}]
276function getWorkHours(json, restaurant_id) {
277 return json.filter(item => item.restaurant_id === restaurant_id);
278}
279function getWorkHoursForDay(json, restaurant_id, day) {
280 return getWorkHours(json, restaurant_id).filter(item => item.day === day);
281}
282let restaurantReserve = {
283 init: function () {
284 let _self = this;
285
286 $('#reservation-date').datepicker({startDate: '+0d'}).on('changeDate', function (e) {
287 const arDate = e.date.toString().split(' ');
288 let input = $('[name="RestaurantReservationForm[date]"]');
289 input.val(arDate[3] + '-' + (e.date.getMonth() + 1) + '-' + arDate[2]);
290 _self.unSetError(input);
291 $('#reservation-date .js-value').text(arDate[2] + ' ' + arDate[1]);
292 });
293
294 $('[aria-labelledby="reservation-time"] li a').click(function () {
295 $(this).closest('ul').find('a').removeClass('active');
296 $(this).addClass('active');
297 let input = $('[name="RestaurantReservationForm[time]"]');
298 input.val($(this).data('value'));
299 _self.unSetError(input);
300 $('#reservation-time .js-value').text($(this).text());
301 });
302 },
303 setError: function (ob) {
304 $('#' + ob.data('btnId')).addClass('btn-error');
305 },
306 unSetError: function (ob) {
307 $('#' + ob.data('btnId')).removeClass('btn-error');
308 }
309 }
310
311 restaurantReserve.init();
312
313 let json = [{"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":91,"restaurant_id":1,"day":"Sat","open":"0","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"}, {"id":107,"restaurant_id":3,"day":"Mon","open":"1.30","close":"19.00","created_at":"2022-02-22 10:58:59"},{"id":108,"restaurant_id":3,"day":"Tue","open":"5.30","close":"8.00","created_at":"2022-02-22 10:58:59"},{"id":109,"restaurant_id":3,"day":"Wed","open":"3.00","close":"20.30","created_at":"2022-02-22 10:58:59"},{"id":110,"restaurant_id":3,"day":"Thu","open":"1.00","close":"12.30","created_at":"2022-02-22 10:58:59"},{"id":111,"restaurant_id":3,"day":"Fri","open":"2.30","close":"12.30","created_at":"2022-02-22 10:58:59"},{"id":112,"restaurant_id":3,"day":"Sat","open":"4.00","close":"22.00","created_at":"2022-02-22 10:58:59"},{"id":113,"restaurant_id":3,"day":"Sun","open":"4.00","close":"22.30","created_at":"2022-02-22 10:58:59"}];
314
315 function getWorkHours(json, restaurant_id) {
316 return json.filter(item => item.restaurant_id == restaurant_id);
317 }
318
319 function getWorkHoursForDay(json, restaurant_id, day) {
320 return getWorkHours(json, restaurant_id).filter(item => item.day === day)[0];
321 }
322
323 function filterTimes() {
324 let restaurantID = document.getElementById("restaurantid").value;
325 let dayofweek = document.getElementById("dayofweek").value;
326 if ((["1", "3"].indexOf(restaurantID) >= 0) && ((["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"].indexOf(dayofweek)) >= 0)) {
327 let workHours = getWorkHoursForDay(json, restaurantID, dayofweek);
328 let items = document.querySelectorAll(".dropdown-menu.dropdown-menu-height-fixed li a");
329 for (let item of items) {
330 let itemValueParts = item.innerText.split(" ");
331 itemValue = parseFloat(itemValueParts[0]) + (((itemValueParts[1] === "PM") && (itemValueParts[0] !== "00.00")) ? 12 : 0);
332 item.parentNode.classList[((itemValue < parseFloat(workHours.open)) || (itemValue > parseFloat(workHours.close)) ? "add" : "remove")]("invisible");
333 }
334 }
335 }.btn {
336 border: none;
337 border-radius: 8px;
338 height: 40px;
339 padding: 10px 15px;
340 font-weight: 800;
341 font-size: 14px;
342 margin-right: 10px;
343 cursor: pointer;
344 }
345
346 .btn-fourth {
347 text-decoration: none;
348 background: #e3e5e8;
349 color: #747b8b;
350 }
351
352 .invisible {
353 display: none;
354 }
355
356 ul.with-out > li:before, .dropdown-menu li:before, ul.whithout > li:before {display:none;}
357
358 .dropdown-menu li {padding:0;}
359
360 .dropdown-menu-height-fixed {max-height:200px;overflow-y:auto;}
361
362 .dropdown-item.active, .dropdown-item:active {background:red;}
363
364 .block-shadow {box-shadow:0 2px 8px 0 rgba(32,35,44,0.05);}
365 .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>[{"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[{"id":107,"restaurant_id":3,"day":"Mon","open":"1.30","close":"19.00","created_at":"2022-02-22 10:58:59"},{"id":108,"restaurant_id":3,"day":"Tue","open":"5.30","close":"8.00","created_at":"2022-02-22 10:58:59"},{"id":109,"restaurant_id":3,"day":"Wed","open":"3.00","close":"20.30","created_at":"2022-02-22 10:58:59"},{"id":110,"restaurant_id":3,"day":"Thu","open":"1.00","close":"12.30","created_at":"2022-02-22 10:58:59"},{"id":111,"restaurant_id":3,"day":"Fri","open":"2.30","close":"12.30","created_at":"2022-02-22 10:58:59"},{"id":112,"restaurant_id":3,"day":"Sat","open":"4.00","close":"22.00","created_at":"2022-02-22 10:58:59"},{"id":113,"restaurant_id":3,"day":"Sun","open":"4.00","close":"22.30","created_at":"2022-02-22 10:58:59"}]
275[{"id":"1","restaurant_id":"1","day":"Mon","open":"9.30","close":"14.30","created_at":"2022-02-15 05:00:57"}]
276function getWorkHours(json, restaurant_id) {
277 return json.filter(item => item.restaurant_id === restaurant_id);
278}
279function getWorkHoursForDay(json, restaurant_id, day) {
280 return getWorkHours(json, restaurant_id).filter(item => item.day === day);
281}
282let restaurantReserve = {
283 init: function () {
284 let _self = this;
285
286 $('#reservation-date').datepicker({startDate: '+0d'}).on('changeDate', function (e) {
287 const arDate = e.date.toString().split(' ');
288 let input = $('[name="RestaurantReservationForm[date]"]');
289 input.val(arDate[3] + '-' + (e.date.getMonth() + 1) + '-' + arDate[2]);
290 _self.unSetError(input);
291 $('#reservation-date .js-value').text(arDate[2] + ' ' + arDate[1]);
292 });
293
294 $('[aria-labelledby="reservation-time"] li a').click(function () {
295 $(this).closest('ul').find('a').removeClass('active');
296 $(this).addClass('active');
297 let input = $('[name="RestaurantReservationForm[time]"]');
298 input.val($(this).data('value'));
299 _self.unSetError(input);
300 $('#reservation-time .js-value').text($(this).text());
301 });
302 },
303 setError: function (ob) {
304 $('#' + ob.data('btnId')).addClass('btn-error');
305 },
306 unSetError: function (ob) {
307 $('#' + ob.data('btnId')).removeClass('btn-error');
308 }
309 }
310
311 restaurantReserve.init();
312
313 let json = [{"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":91,"restaurant_id":1,"day":"Sat","open":"0","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"}, {"id":107,"restaurant_id":3,"day":"Mon","open":"1.30","close":"19.00","created_at":"2022-02-22 10:58:59"},{"id":108,"restaurant_id":3,"day":"Tue","open":"5.30","close":"8.00","created_at":"2022-02-22 10:58:59"},{"id":109,"restaurant_id":3,"day":"Wed","open":"3.00","close":"20.30","created_at":"2022-02-22 10:58:59"},{"id":110,"restaurant_id":3,"day":"Thu","open":"1.00","close":"12.30","created_at":"2022-02-22 10:58:59"},{"id":111,"restaurant_id":3,"day":"Fri","open":"2.30","close":"12.30","created_at":"2022-02-22 10:58:59"},{"id":112,"restaurant_id":3,"day":"Sat","open":"4.00","close":"22.00","created_at":"2022-02-22 10:58:59"},{"id":113,"restaurant_id":3,"day":"Sun","open":"4.00","close":"22.30","created_at":"2022-02-22 10:58:59"}];
314
315 function getWorkHours(json, restaurant_id) {
316 return json.filter(item => item.restaurant_id == restaurant_id);
317 }
318
319 function getWorkHoursForDay(json, restaurant_id, day) {
320 return getWorkHours(json, restaurant_id).filter(item => item.day === day)[0];
321 }
322
323 function filterTimes() {
324 let restaurantID = document.getElementById("restaurantid").value;
325 let dayofweek = document.getElementById("dayofweek").value;
326 if ((["1", "3"].indexOf(restaurantID) >= 0) && ((["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"].indexOf(dayofweek)) >= 0)) {
327 let workHours = getWorkHoursForDay(json, restaurantID, dayofweek);
328 let items = document.querySelectorAll(".dropdown-menu.dropdown-menu-height-fixed li a");
329 for (let item of items) {
330 let itemValueParts = item.innerText.split(" ");
331 itemValue = parseFloat(itemValueParts[0]) + (((itemValueParts[1] === "PM") && (itemValueParts[0] !== "00.00")) ? 12 : 0);
332 item.parentNode.classList[((itemValue < parseFloat(workHours.open)) || (itemValue > parseFloat(workHours.close)) ? "add" : "remove")]("invisible");
333 }
334 }
335 }.btn {
336 border: none;
337 border-radius: 8px;
338 height: 40px;
339 padding: 10px 15px;
340 font-weight: 800;
341 font-size: 14px;
342 margin-right: 10px;
343 cursor: pointer;
344 }
345
346 .btn-fourth {
347 text-decoration: none;
348 background: #e3e5e8;
349 color: #747b8b;
350 }
351
352 .invisible {
353 display: none;
354 }
355
356 ul.with-out > li:before, .dropdown-menu li:before, ul.whithout > li:before {display:none;}
357
358 .dropdown-menu li {padding:0;}
359
360 .dropdown-menu-height-fixed {max-height:200px;overflow-y:auto;}
361
362 .dropdown-item.active, .dropdown-item:active {background:red;}
363
364 .block-shadow {box-shadow:0 2px 8px 0 rgba(32,35,44,0.05);}
365 .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>
366 <link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.9.0/css/bootstrap-datepicker.min.css" rel="stylesheet">
367 <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.9.0/js/bootstrap-datepicker.min.js"></script>
368
369 <form id="reservation" action="/restaurants/123/" method="post">
370 <div class="block-shadow block-white mb-4">
371 <h5 class="fw-bold mb-3">Reserve a table</h5>
372 <div class="btn-s">
373 <a class="btn btn-fourth "
374 id="reservation-date"
375 data-date=">">
376 <span class="icon br-calender"></span> <span class="js-value">
377 -- --- </span>
378 </a>
379 <a class="btn btn-fourth "
380 id="reservation-time" role="button" data-bs-toggle="dropdown" aria-expanded="false">
381 <span class="icon br-clock"></span> <span class="js-value">
382 -- : -- </span>
383 </a>
384 <select id="restaurantid" onchange="filterTimes()">
385 <option>Please Select Restaurant</option>
386 <option value="1">Pizza Mia</option>
387 <option value="3">Burger Land</option>
388 </select>
389 <select id="dayofweek" onchange="filterTimes()">
390 <option>Please Select Day</option>
391 <option value="Mon">Mon</option>
392 <option value="Tue">Tue</option>
393 <option value="Wed">Wed</option>
394 <option value="Thu">Thu</option>
395 <option value="Fri">Fri</option>
396 <option value="Sat">Sat</option>
397 <option value="Sun">Sun</option>
398 </select>
399 <ul class="dropdown-menu dropdown-menu-height-fixed" aria-labelledby="reservation-time">
400 <li><a class="dropdown-item " href="#" data-value="0.00">00.00 PM</a></li>
401 <li><a class="dropdown-item " href="#" data-value="0.30">00.30 AM</a></li>
402 <li><a class="dropdown-item " href="#" data-value="1.00">01.00 AM</a></li>
403 <li><a class="dropdown-item " href="#" data-value="1.30">01.30 AM</a></li>
404 <li><a class="dropdown-item " href="#" data-value="2.00">02.00 AM</a></li>
405 <li><a class="dropdown-item " href="#" data-value="2.30">02.30 AM</a></li>
406 <li><a class="dropdown-item " href="#" data-value="3.00">03.00 AM</a></li>
407 <li><a class="dropdown-item " href="#" data-value="3.30">03.30 AM</a></li>
408 <li><a class="dropdown-item " href="#" data-value="4.00">04.00 AM</a></li>
409 <li><a class="dropdown-item " href="#" data-value="4.30">04.30 AM</a></li>
410 <li><a class="dropdown-item " href="#" data-value="5.00">05.00 AM</a></li>
411 <li><a class="dropdown-item " href="#" data-value="5.30">05.30 AM</a></li>
412 <li><a class="dropdown-item " href="#" data-value="6.00">06.00 AM</a></li>
413 <li><a class="dropdown-item " href="#" data-value="6.30">06.30 AM</a></li>
414 <li><a class="dropdown-item " href="#" data-value="7.00">07.00 AM</a></li>
415 <li><a class="dropdown-item " href="#" data-value="7.30">07.30 AM</a></li>
416 <li><a class="dropdown-item " href="#" data-value="8.00">08.00 AM</a></li>
417 <li><a class="dropdown-item " href="#" data-value="8.30">08.30 AM</a></li>
418 <li><a class="dropdown-item " href="#" data-value="9.00">09.00 AM</a></li>
419 <li><a class="dropdown-item " href="#" data-value="9.30">09.30 AM</a></li>
420 <li><a class="dropdown-item " href="#" data-value="10.00">10.00 AM</a></li>
421 <li><a class="dropdown-item " href="#" data-value="10.30">10.30 AM</a></li>
422 <li><a class="dropdown-item " href="#" data-value="11.00">11.00 AM</a></li>
423 <li><a class="dropdown-item " href="#" data-value="11.30">11.30 AM</a></li>
424 <li><a class="dropdown-item " href="#" data-value="12.00">00.00 AM</a></li>
425 <li><a class="dropdown-item " href="#" data-value="12.30">00.30 PM</a></li>
426 <li><a class="dropdown-item " href="#" data-value="13.00">01.00 PM</a></li>
427 <li><a class="dropdown-item " href="#" data-value="13.30">01.30 PM</a></li>
428 <li><a class="dropdown-item " href="#" data-value="14.00">02.00 PM</a></li>
429 <li><a class="dropdown-item " href="#" data-value="14.30">02.30 PM</a></li>
430 <li><a class="dropdown-item " href="#" data-value="15.00">03.00 PM</a></li>
431 <li><a class="dropdown-item " href="#" data-value="15.30">03.30 PM</a></li>
432 <li><a class="dropdown-item " href="#" data-value="16.00">04.00 PM</a></li>
433 <li><a class="dropdown-item " href="#" data-value="16.30">04.30 PM</a></li>
434 <li><a class="dropdown-item " href="#" data-value="17.00">05.00 PM</a></li>
435 <li><a class="dropdown-item " href="#" data-value="17.30">05.30 PM</a></li>
436 <li><a class="dropdown-item " href="#" data-value="18.00">06.00 PM</a></li>
437 <li><a class="dropdown-item " href="#" data-value="18.30">06.30 PM</a></li>
438 <li><a class="dropdown-item " href="#" data-value="19.00">07.00 PM</a></li>
439 <li><a class="dropdown-item " href="#" data-value="19.30">07.30 PM</a></li>
440 <li><a class="dropdown-item " href="#" data-value="20.00">08.00 PM</a></li>
441 <li><a class="dropdown-item " href="#" data-value="20.30">08.30 PM</a></li>
442 <li><a class="dropdown-item " href="#" data-value="21.00">09.00 PM</a></li>
443 <li><a class="dropdown-item " href="#" data-value="21.30">09.30 PM</a></li>
444 <li><a class="dropdown-item " href="#" data-value="22.00">10.00 PM</a></li>
445 <li><a class="dropdown-item " href="#" data-value="22.30">10.30 PM</a></li>
446 <li><a class="dropdown-item " href="#" data-value="23.00">11.00 PM</a></li>
447 <li><a class="dropdown-item " href="#" data-value="23.30">11.30 PM</a></li>
448 </ul>
449 </div>
450 <div class="form-group field-restaurantreservationform-personcount">
451 <input type="hidden" id="restaurantreservationform-personcount" class="form-control" name="RestaurantReservationForm[personCount]" data-btn-id="reservation-person">
452 </div> <div class="form-group field-restaurantreservationform-date required">
453 <input type="hidden" id="restaurantreservationform-date" class="form-control" name="RestaurantReservationForm[date]" data-btn-id="reservation-date">
454 </div> <div class="form-group field-restaurantreservationform-time">
455 <input type="hidden" id="restaurantreservationform-time" class="form-control" name="RestaurantReservationForm[time]" data-btn-id="reservation-time">
456 </div>
QUESTION
Module not found: Error: Can't resolve 'date-fns/addDays' in 'C:\Users\
Asked 2022-Feb-08 at 17:19I want to use Date picker from MUI but I get this error and I don't know what exactly is wrong. here is my code:
1import TextField from "@mui/material/TextField";
2import DatePicker from "@mui/lab/DatePicker";
3import AdapterDateFns from "@mui/lab/AdapterDateFns";
4import LocalizationProvider from "@mui/lab/LocalizationProvider";
5
6const ExpenseForm = () => {
7 return (
8 <Box component="form" noValidate autoComplete="off">
9 <LocalizationProvider dateAdapter={AdapterDateFns}>
10 <DatePicker
11 label="Basic example"
12 onChange={(newValue) => {}}
13 renderInput={(params) => <TextField {...params} />}
14 />
15 </LocalizationProvider>
16 </Box>
17 );
18};
19
20export default ExpenseForm;
21
and my package.json:
1import TextField from "@mui/material/TextField";
2import DatePicker from "@mui/lab/DatePicker";
3import AdapterDateFns from "@mui/lab/AdapterDateFns";
4import LocalizationProvider from "@mui/lab/LocalizationProvider";
5
6const ExpenseForm = () => {
7 return (
8 <Box component="form" noValidate autoComplete="off">
9 <LocalizationProvider dateAdapter={AdapterDateFns}>
10 <DatePicker
11 label="Basic example"
12 onChange={(newValue) => {}}
13 renderInput={(params) => <TextField {...params} />}
14 />
15 </LocalizationProvider>
16 </Box>
17 );
18};
19
20export default ExpenseForm;
21"dependencies": {
22 "@date-io/date-fns": "^2.13.1",
23 "@emotion/react": "^11.7.1",
24 "@emotion/styled": "^11.6.0",
25 "@mui/icons-material": "^5.3.1",
26 "@mui/lab": "^5.0.0-alpha.68",
27 "@mui/material": "^5.4.0",
28 "@testing-library/jest-dom": "^5.16.1",
29 "@testing-library/react": "^12.1.2",
30 "@testing-library/user-event": "^13.5.0",
31 "react": "^17.0.2",
32 "react-dom": "^17.0.2",
33 "react-scripts": "5.0.0",
34 "web-vitals": "^2.1.4"
35 },
36
but everytime I get these errors:
1import TextField from "@mui/material/TextField";
2import DatePicker from "@mui/lab/DatePicker";
3import AdapterDateFns from "@mui/lab/AdapterDateFns";
4import LocalizationProvider from "@mui/lab/LocalizationProvider";
5
6const ExpenseForm = () => {
7 return (
8 <Box component="form" noValidate autoComplete="off">
9 <LocalizationProvider dateAdapter={AdapterDateFns}>
10 <DatePicker
11 label="Basic example"
12 onChange={(newValue) => {}}
13 renderInput={(params) => <TextField {...params} />}
14 />
15 </LocalizationProvider>
16 </Box>
17 );
18};
19
20export default ExpenseForm;
21"dependencies": {
22 "@date-io/date-fns": "^2.13.1",
23 "@emotion/react": "^11.7.1",
24 "@emotion/styled": "^11.6.0",
25 "@mui/icons-material": "^5.3.1",
26 "@mui/lab": "^5.0.0-alpha.68",
27 "@mui/material": "^5.4.0",
28 "@testing-library/jest-dom": "^5.16.1",
29 "@testing-library/react": "^12.1.2",
30 "@testing-library/user-event": "^13.5.0",
31 "react": "^17.0.2",
32 "react-dom": "^17.0.2",
33 "react-scripts": "5.0.0",
34 "web-vitals": "^2.1.4"
35 },
36Compiled with problems:
37
38ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 1:0-39
39
40Module not found: Error: Can't resolve 'date-fns/addDays' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
41
42
43ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 2:0-45
44
45Module not found: Error: Can't resolve 'date-fns/addSeconds' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
46
47
48ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 3:0-45
49
50Module not found: Error: Can't resolve 'date-fns/addMinutes' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
51
52
53ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 4:0-41
54
55Module not found: Error: Can't resolve 'date-fns/addHours' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
56
57
58ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 5:0-41
59
60Module not found: Error: Can't resolve 'date-fns/addWeeks' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
61
62
63ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 6:0-43
64
65Module not found: Error: Can't resolve 'date-fns/addMonths' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
66
67
68ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 7:0-41
69
70Module not found: Error: Can't resolve 'date-fns/addYears' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
71
72
73ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 8:0-59
74
75Module not found: Error: Can't resolve 'date-fns/differenceInYears' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
76
77
78ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 9:0-65
79
80Module not found: Error: Can't resolve 'date-fns/differenceInQuarters' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
81
82
83ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 10:0-61
84
85Module not found: Error: Can't resolve 'date-fns/differenceInMonths' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
86
87
88ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 11:0-59
89
90Module not found: Error: Can't resolve 'date-fns/differenceInWeeks' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
91
92
93ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 12:0-57
94
95Module not found: Error: Can't resolve 'date-fns/differenceInDays' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
96
97
98ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 13:0-59
99
100Module not found: Error: Can't resolve 'date-fns/differenceInHours' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
101
102
103ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 14:0-63
104
105Module not found: Error: Can't resolve 'date-fns/differenceInMinutes' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
106
107
108ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 15:0-63
109
110Module not found: Error: Can't resolve 'date-fns/differenceInSeconds' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
111
112
113ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 16:0-73
114
115Module not found: Error: Can't resolve 'date-fns/differenceInMilliseconds' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
116
117
118ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 17:0-59
119
120Module not found: Error: Can't resolve 'date-fns/eachDayOfInterval' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
121
122
123ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 18:0-41
124
125Module not found: Error: Can't resolve 'date-fns/endOfDay' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
126
127
128ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 19:0-43
129
130Module not found: Error: Can't resolve 'date-fns/endOfWeek' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
131
132
133ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 20:0-43
134
135Module not found: Error: Can't resolve 'date-fns/endOfYear' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
136
137
138ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 21:0-37
139
140Module not found: Error: Can't resolve 'date-fns/format' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
141
142
143ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 22:0-41
144
145Module not found: Error: Can't resolve 'date-fns/getHours' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
146
147
148ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 23:0-45
149
150Module not found: Error: Can't resolve 'date-fns/getSeconds' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
151
152
153ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 24:0-39
154
155Module not found: Error: Can't resolve 'date-fns/getYear' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
156
157
158ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 25:0-39
159
160Module not found: Error: Can't resolve 'date-fns/isAfter' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
161
162
163ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 26:0-41
164
165Module not found: Error: Can't resolve 'date-fns/isBefore' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
166
167
168ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 27:0-39
169
170Module not found: Error: Can't resolve 'date-fns/isEqual' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
171
172
173ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 28:0-43
174
175Module not found: Error: Can't resolve 'date-fns/isSameDay' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
176
177
178ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 29:0-45
179
180Module not found: Error: Can't resolve 'date-fns/isSameYear' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
181
182
183ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 30:0-47
184
185Module not found: Error: Can't resolve 'date-fns/isSameMonth' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
186
187
188ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 31:0-45
189
190Module not found: Error: Can't resolve 'date-fns/isSameHour' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
191
192
193ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 32:0-39
194
195Module not found: Error: Can't resolve 'date-fns/isValid' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
196
197
198ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 33:0-42
199
200Module not found: Error: Can't resolve 'date-fns/parse' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
201
202
203ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 34:0-41
204
205Module not found: Error: Can't resolve 'date-fns/setHours' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
206
207
208ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 35:0-45
209
210Module not found: Error: Can't resolve 'date-fns/setMinutes' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
211
212
213ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 36:0-41
214
215Module not found: Error: Can't resolve 'date-fns/setMonth' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
216
217
218ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 37:0-37
219
220Module not found: Error: Can't resolve 'date-fns/getDay' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
221
222
223ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 38:0-53
224
225Module not found: Error: Can't resolve 'date-fns/getDaysInMonth' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
226
227
228ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 39:0-45
229
230Module not found: Error: Can't resolve 'date-fns/setSeconds' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
231
232
233ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 40:0-39
234
235Module not found: Error: Can't resolve 'date-fns/setYear' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
236
237
238ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 41:0-45
239
240Module not found: Error: Can't resolve 'date-fns/startOfDay' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
241
242
243ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 42:0-49
244
245Module not found: Error: Can't resolve 'date-fns/startOfMonth' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
246
247
248ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 43:0-45
249
250Module not found: Error: Can't resolve 'date-fns/endOfMonth' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
251
252
253ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 44:0-47
254
255Module not found: Error: Can't resolve 'date-fns/startOfWeek' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
256
257
258ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 45:0-47
259
260Module not found: Error: Can't resolve 'date-fns/startOfYear' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
261
262
263ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 46:0-41
264
265Module not found: Error: Can't resolve 'date-fns/parseISO' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
266
267
268ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 47:0-43
269
270Module not found: Error: Can't resolve 'date-fns/formatISO' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
271
272
273ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 48:0-57
274
275Module not found: Error: Can't resolve 'date-fns/isWithinInterval' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
276
277
278ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 49:0-65
279
280Module not found: Error: Can't resolve 'date-fns/_lib/format/longFormatters' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
281
282
283ERROR in ./node_modules/@date-io/date-fns/build/index.esm.js 50:0-50
284
285Module not found: Error: Can't resolve 'date-fns/locale/en-US' in 'C:\Users\Amir\Desktop\React\React-apps\expense-tracker\node_modules\@date-io\date-fns\build'
286
I searched the web but couldn't find something useful . also some StackOverflow similar posts that suggested to restart the server I tried but didn't actually solve my problem.
ANSWER
Answered 2022-Feb-08 at 17:19You need to install the date-fns
package from NPM using npm install --save date-fns
.
QUESTION
Why does MUI DatePicker prevent rendering in my project (working sandbox MRE included?)
Asked 2022-Feb-01 at 08:42I created a codesandbox with a minimal working implementation of MUI's Datepicker:
https://codesandbox.io/s/proud-pond-fb4rm?file=/src/App.js
*Edited to add my index.tsx:
1import React from 'react';
2import ReactDOM from 'react-dom';
3import {DatePicker, LocalizationProvider} from "@mui/lab";
4import {TextField} from "@mui/material";
5import AdapterDateFns from "@mui/lab/AdapterDateFns";
6
7ReactDOM.render(
8 <LocalizationProvider dateAdapter={AdapterDateFns}>
9 <DatePicker
10 renderInput={(props) => <TextField {...props} />}
11 value={null}
12 onChange={() => null}
13 />
14 </LocalizationProvider>
15 , document.getElementById('root')
16)
17
This implementation throws errors in my project (prevents rendering), although I have the same versions installed. I linked my package-lock file for good measure in case I'm wrong.
Clearly not a bug, and seemingly not a mismatch in package versions, what else could be causing this?
ANSWER
Answered 2022-Feb-01 at 08:42As suspected, the clue was in my package-lock.json. Note to self: Always a good idea to have a look there when issue has been isolated and confirmed unique to a given project!
I had two different versions of @date-io/date-fns installed:
- 1.x.x (entry in package-json)
- 2.x.x (installed as dependency)
QUESTION
Using the MUI DatePicker with yup and react-hook-form - the error prop doesn't work as intended
Asked 2022-Jan-09 at 13:32I'm working on a registration form made with yup, react-hook-form and MUI DatePicker/TextField. I'd like to have a date of birth field that checks if the user is above 18 years old. The error message is displayed correcly but the red color of the error state works only if the input is empty (and not when the age is below 18). I'm console logging the value of "invalid" that dictates the red color, and it is set to true when it should.
Here is a sandbox link: https://codesandbox.io/s/datepicker-yup-validation-8rod3?file=/src/App.js
ANSWER
Answered 2022-Jan-09 at 06:04this solution was wrote with formik , yup and material datepicker :
1 import "./styles.css";
2import LocalizationProvider from "@mui/lab/LocalizationProvider";
3import AdapterDateFns from "@mui/lab/AdapterDateFns";
4import DateTimePicker from "@mui/lab/DateTimePicker";
5import * as Yup from "yup";
6import { useFormik } from "formik";
7import { Button, TextField } from "@mui/material";
8import moment from "moment";
9var y = new Date();
10y.setFullYear(y.getFullYear() - 18);
11
12const validationSchema = Yup.object().shape({
13 voyageNumber: Yup.number(),
14 voyageStartDate: Yup.date(),
15 voyageEndDate: Yup.date().when("voyageStartDate", (voyageStartDate, schema) =>
16 moment(voyageStartDate).isValid() ? schema.max(voyageStartDate) : schema
17 )
18});
19export default function App() {
20 const formik = useFormik({
21 initialValues: {
22 voyageStartDate: moment().add(-18, "years"),
23 voyageEndDate: null
24 },
25 validationSchema: validationSchema,
26 onSubmit: (values) => {
27 console.log(values);
28 }
29 });
30 return (
31 <div className="App">
32 <form autoComplete="off">
33 <LocalizationProvider dateAdapter={AdapterDateFns}>
34 <DateTimePicker
35 renderInput={(props) => (
36 <TextField
37 variant="standard"
38 className="w-100"
39 name="voyageEndDate"
40 required
41 {...props}
42 error={
43 formik.touched?.voyageEndDate &&
44 !!formik.errors?.voyageEndDate
45 }
46 helperText={
47 formik.touched?.voyageEndDate && formik.errors?.voyageEndDate
48 }
49 />
50 )}
51 name="voyageEndDate"
52 label="Voyage End"
53 value={formik.values?.voyageEndDate}
54 onChange={(newValue) => {
55 console.log(
56 moment(newValue).format("YYYY-MM-DD HH:mm:ss"),
57 moment(y).format("YYYY-MM-DD HH:mm:ss"),
58 formik.errors
59 );
60 formik.setFieldTouched("voyageEndDate");
61 formik.setFieldValue(
62 "voyageEndDate",
63 moment(newValue).format("YYYY-MM-DD HH:mm:ss")
64 );
65 }}
66 onKeyPress={() => formik.setFieldTouched("voyageEndDate")}
67 />
68 </LocalizationProvider>
69 <div style={{ marginTop: "15px" }}>
70 <Button variant="contained" color="primary" type="submit">
71 Add Voyage
72 </Button>
73 </div>
74 </form>
75 </div>
76 );
77}
78
QUESTION
JavaFX: Exception in Application Start Method java.lang.reflect.InvocationTargetException
Asked 2021-Dec-10 at 19:28I am literally desperate. I don’t know why but every time I try to run my program this error comes out. I am using Netbeans, with Java 10.0.2 in order to have already installed JavaFX. I think it’s due to some problem with the FXML file. Can you help me?
1java.lang.reflect.InvocationTargetException
2 at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
3 at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
4 at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
5 at java.base/java.lang.reflect.Method.invoke(Method.java:564)
6 at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:473)
7 at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:372)
8 at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
9 at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
10 at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
11 at java.base/java.lang.reflect.Method.invoke(Method.java:564)
12 at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:941)
13Caused by: java.lang.RuntimeException: Exception in Application start method
14 at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:973)
15 at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:198)
16 at java.base/java.lang.Thread.run(Thread.java:844)
17Caused by: javafx.fxml.LoadException: Root hasn't been set. Use method setRoot() before load.
18file:/C:/Users/User/Documents/NetBeansProjects/gruppo71/dist/run2124011701/gruppo71.jar!/gruppo71/FXMLDocument.fxml:13
19
20 at javafx.fxml/javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2621)
21 at javafx.fxml/javafx.fxml.FXMLLoader.access$100(FXMLLoader.java:105)
22 at javafx.fxml/javafx.fxml.FXMLLoader$RootElement.constructValue(FXMLLoader.java:1338)
23 at javafx.fxml/javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:754)
24 at javafx.fxml/javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2722)
25 at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2552)
26 at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2466)
27 at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3253)
28 at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3210)
29 at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3179)
30 at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3152)
31 at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3129)
32 at javafx.fxml/javafx.fxml.FXMLLoader.load(FXMLLoader.java:3122)
33 at gruppo71.Gruppo71.start(Gruppo71.java:21)
34 at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:919)
35 at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$11(PlatformImpl.java:449)
36 at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$9(PlatformImpl.java:418)
37 at java.base/java.security.AccessController.doPrivileged(Native Method)
38 at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:417)
39 at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
40 at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
41 at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:175)
42 ... 1 more
43Exception running application gruppo71.Gruppo71
44Java Result: 1
45
My main is this:
1java.lang.reflect.InvocationTargetException
2 at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
3 at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
4 at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
5 at java.base/java.lang.reflect.Method.invoke(Method.java:564)
6 at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:473)
7 at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:372)
8 at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
9 at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
10 at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
11 at java.base/java.lang.reflect.Method.invoke(Method.java:564)
12 at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:941)
13Caused by: java.lang.RuntimeException: Exception in Application start method
14 at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:973)
15 at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:198)
16 at java.base/java.lang.Thread.run(Thread.java:844)
17Caused by: javafx.fxml.LoadException: Root hasn't been set. Use method setRoot() before load.
18file:/C:/Users/User/Documents/NetBeansProjects/gruppo71/dist/run2124011701/gruppo71.jar!/gruppo71/FXMLDocument.fxml:13
19
20 at javafx.fxml/javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2621)
21 at javafx.fxml/javafx.fxml.FXMLLoader.access$100(FXMLLoader.java:105)
22 at javafx.fxml/javafx.fxml.FXMLLoader$RootElement.constructValue(FXMLLoader.java:1338)
23 at javafx.fxml/javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:754)
24 at javafx.fxml/javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2722)
25 at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2552)
26 at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2466)
27 at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3253)
28 at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3210)
29 at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3179)
30 at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3152)
31 at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3129)
32 at javafx.fxml/javafx.fxml.FXMLLoader.load(FXMLLoader.java:3122)
33 at gruppo71.Gruppo71.start(Gruppo71.java:21)
34 at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:919)
35 at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$11(PlatformImpl.java:449)
36 at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$9(PlatformImpl.java:418)
37 at java.base/java.security.AccessController.doPrivileged(Native Method)
38 at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:417)
39 at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
40 at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
41 at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:175)
42 ... 1 more
43Exception running application gruppo71.Gruppo71
44Java Result: 1
45
46import javafx.application.Application;
47import javafx.fxml.FXMLLoader;
48import javafx.scene.Parent;
49import javafx.scene.Scene;
50import javafx.stage.Stage;
51
52/**
53 *
54 * @author User
55 */
56public class Gruppo71 extends Application {
57
58 @Override
59 public void start(Stage stage) throws Exception {
60 Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
61
62 Scene scene = new Scene(root);
63
64 stage.setScene(scene);
65 stage.show();
66 }
67
68 /**
69 * @param args the command line arguments
70 */
71 public static void main(String[] args) {
72 launch(args);
73 }
74}
75
My FXML code is:
1java.lang.reflect.InvocationTargetException
2 at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
3 at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
4 at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
5 at java.base/java.lang.reflect.Method.invoke(Method.java:564)
6 at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:473)
7 at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:372)
8 at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
9 at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
10 at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
11 at java.base/java.lang.reflect.Method.invoke(Method.java:564)
12 at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:941)
13Caused by: java.lang.RuntimeException: Exception in Application start method
14 at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:973)
15 at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:198)
16 at java.base/java.lang.Thread.run(Thread.java:844)
17Caused by: javafx.fxml.LoadException: Root hasn't been set. Use method setRoot() before load.
18file:/C:/Users/User/Documents/NetBeansProjects/gruppo71/dist/run2124011701/gruppo71.jar!/gruppo71/FXMLDocument.fxml:13
19
20 at javafx.fxml/javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2621)
21 at javafx.fxml/javafx.fxml.FXMLLoader.access$100(FXMLLoader.java:105)
22 at javafx.fxml/javafx.fxml.FXMLLoader$RootElement.constructValue(FXMLLoader.java:1338)
23 at javafx.fxml/javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:754)
24 at javafx.fxml/javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2722)
25 at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2552)
26 at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2466)
27 at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3253)
28 at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3210)
29 at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3179)
30 at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3152)
31 at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3129)
32 at javafx.fxml/javafx.fxml.FXMLLoader.load(FXMLLoader.java:3122)
33 at gruppo71.Gruppo71.start(Gruppo71.java:21)
34 at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:919)
35 at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$11(PlatformImpl.java:449)
36 at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$9(PlatformImpl.java:418)
37 at java.base/java.security.AccessController.doPrivileged(Native Method)
38 at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:417)
39 at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
40 at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
41 at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:175)
42 ... 1 more
43Exception running application gruppo71.Gruppo71
44Java Result: 1
45
46import javafx.application.Application;
47import javafx.fxml.FXMLLoader;
48import javafx.scene.Parent;
49import javafx.scene.Scene;
50import javafx.stage.Stage;
51
52/**
53 *
54 * @author User
55 */
56public class Gruppo71 extends Application {
57
58 @Override
59 public void start(Stage stage) throws Exception {
60 Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
61
62 Scene scene = new Scene(root);
63
64 stage.setScene(scene);
65 stage.show();
66 }
67
68 /**
69 * @param args the command line arguments
70 */
71 public static void main(String[] args) {
72 launch(args);
73 }
74}
75
76<?import javafx.scene.control.Button?>
77<?import javafx.scene.control.ContextMenu?>
78<?import javafx.scene.control.DatePicker?>
79<?import javafx.scene.control.MenuItem?>
80<?import javafx.scene.control.SplitPane?>
81<?import javafx.scene.control.TableColumn?>
82<?import javafx.scene.control.TableView?>
83<?import javafx.scene.control.TextField?>
84<?import javafx.scene.layout.AnchorPane?>
85
86<fx:root id="AnchorPane" prefHeight="300.0" prefWidth="450.0" type="AnchorPane" xmlns="http://javafx.com/javafx/10.0.2" xmlns:fx="http://javafx.com/fxml/1" fx:controller="gruppo71.FXMLDocumentController">
87 <children>
88 <SplitPane dividerPositions="0.13087248322147652" layoutX="28.0" orientation="VERTICAL" prefHeight="200.0" prefWidth="320.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
89 <items>
90 <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="100.0" prefWidth="160.0">
91 <children>
92 <Button fx:id="aggiungiButton" layoutX="10.0" layoutY="5.0" mnemonicParsing="false" onAction="#addEvento" text="Aggiungi Evento" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="10.0" AnchorPane.topAnchor="5.0" />
93 <DatePicker fx:id="dataPicker" layoutX="114.0" layoutY="6.0" prefHeight="26.0" prefWidth="150.0" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="124.0" AnchorPane.topAnchor="5.0" />
94 <TextField fx:id="descriptionField" layoutX="285.0" layoutY="6.0" text="aggiungi descrizione..." AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="284.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="5.0" />
95 </children>
96 </AnchorPane>
97 <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="100.0" prefWidth="160.0">
98 <children>
99 <TableView fx:id="mainTab" layoutX="14.0" prefHeight="256.0" prefWidth="448.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
100 <columns>
101 <TableColumn fx:id="dataColumn" prefWidth="136.0" text="Data" />
102 <TableColumn fx:id="eventColumn" prefWidth="311.0" text="Evento" />
103 </columns>
104 <contextMenu>
105 <ContextMenu>
106 <items>
107 <MenuItem fx:id="removeButton" mnemonicParsing="false" onAction="#removeEvent" text="Rimuovi Evento" />
108 <MenuItem fx:id="importaButton" mnemonicParsing="false" onAction="#importCSV" text="Importa CSV" />
109 <MenuItem fx:id="exportButton" mnemonicParsing="false" onAction="#exportCSV" text="Esporta CSV" />
110 </items>
111 </ContextMenu>
112 </contextMenu>
113 </TableView>
114 </children>
115 </AnchorPane>
116 </items>
117 </SplitPane>
118 </children>
119</fx:root>
120
All help would be greatly appreciated!!!
ANSWER
Answered 2021-Dec-10 at 19:28Just to mark this as answered: See @James_D' comment for the solution.
Replace <fx:root>
in the FXML file with <AnchorPane>
or set the root on the FXMLLoader
before calling load()
for example like this:
1java.lang.reflect.InvocationTargetException
2 at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
3 at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
4 at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
5 at java.base/java.lang.reflect.Method.invoke(Method.java:564)
6 at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:473)
7 at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:372)
8 at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
9 at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
10 at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
11 at java.base/java.lang.reflect.Method.invoke(Method.java:564)
12 at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:941)
13Caused by: java.lang.RuntimeException: Exception in Application start method
14 at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:973)
15 at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:198)
16 at java.base/java.lang.Thread.run(Thread.java:844)
17Caused by: javafx.fxml.LoadException: Root hasn't been set. Use method setRoot() before load.
18file:/C:/Users/User/Documents/NetBeansProjects/gruppo71/dist/run2124011701/gruppo71.jar!/gruppo71/FXMLDocument.fxml:13
19
20 at javafx.fxml/javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2621)
21 at javafx.fxml/javafx.fxml.FXMLLoader.access$100(FXMLLoader.java:105)
22 at javafx.fxml/javafx.fxml.FXMLLoader$RootElement.constructValue(FXMLLoader.java:1338)
23 at javafx.fxml/javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:754)
24 at javafx.fxml/javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2722)
25 at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2552)
26 at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2466)
27 at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3253)
28 at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3210)
29 at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3179)
30 at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3152)
31 at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3129)
32 at javafx.fxml/javafx.fxml.FXMLLoader.load(FXMLLoader.java:3122)
33 at gruppo71.Gruppo71.start(Gruppo71.java:21)
34 at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:919)
35 at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$11(PlatformImpl.java:449)
36 at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$9(PlatformImpl.java:418)
37 at java.base/java.security.AccessController.doPrivileged(Native Method)
38 at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:417)
39 at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
40 at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
41 at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:175)
42 ... 1 more
43Exception running application gruppo71.Gruppo71
44Java Result: 1
45
46import javafx.application.Application;
47import javafx.fxml.FXMLLoader;
48import javafx.scene.Parent;
49import javafx.scene.Scene;
50import javafx.stage.Stage;
51
52/**
53 *
54 * @author User
55 */
56public class Gruppo71 extends Application {
57
58 @Override
59 public void start(Stage stage) throws Exception {
60 Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
61
62 Scene scene = new Scene(root);
63
64 stage.setScene(scene);
65 stage.show();
66 }
67
68 /**
69 * @param args the command line arguments
70 */
71 public static void main(String[] args) {
72 launch(args);
73 }
74}
75
76<?import javafx.scene.control.Button?>
77<?import javafx.scene.control.ContextMenu?>
78<?import javafx.scene.control.DatePicker?>
79<?import javafx.scene.control.MenuItem?>
80<?import javafx.scene.control.SplitPane?>
81<?import javafx.scene.control.TableColumn?>
82<?import javafx.scene.control.TableView?>
83<?import javafx.scene.control.TextField?>
84<?import javafx.scene.layout.AnchorPane?>
85
86<fx:root id="AnchorPane" prefHeight="300.0" prefWidth="450.0" type="AnchorPane" xmlns="http://javafx.com/javafx/10.0.2" xmlns:fx="http://javafx.com/fxml/1" fx:controller="gruppo71.FXMLDocumentController">
87 <children>
88 <SplitPane dividerPositions="0.13087248322147652" layoutX="28.0" orientation="VERTICAL" prefHeight="200.0" prefWidth="320.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
89 <items>
90 <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="100.0" prefWidth="160.0">
91 <children>
92 <Button fx:id="aggiungiButton" layoutX="10.0" layoutY="5.0" mnemonicParsing="false" onAction="#addEvento" text="Aggiungi Evento" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="10.0" AnchorPane.topAnchor="5.0" />
93 <DatePicker fx:id="dataPicker" layoutX="114.0" layoutY="6.0" prefHeight="26.0" prefWidth="150.0" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="124.0" AnchorPane.topAnchor="5.0" />
94 <TextField fx:id="descriptionField" layoutX="285.0" layoutY="6.0" text="aggiungi descrizione..." AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="284.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="5.0" />
95 </children>
96 </AnchorPane>
97 <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="100.0" prefWidth="160.0">
98 <children>
99 <TableView fx:id="mainTab" layoutX="14.0" prefHeight="256.0" prefWidth="448.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
100 <columns>
101 <TableColumn fx:id="dataColumn" prefWidth="136.0" text="Data" />
102 <TableColumn fx:id="eventColumn" prefWidth="311.0" text="Evento" />
103 </columns>
104 <contextMenu>
105 <ContextMenu>
106 <items>
107 <MenuItem fx:id="removeButton" mnemonicParsing="false" onAction="#removeEvent" text="Rimuovi Evento" />
108 <MenuItem fx:id="importaButton" mnemonicParsing="false" onAction="#importCSV" text="Importa CSV" />
109 <MenuItem fx:id="exportButton" mnemonicParsing="false" onAction="#exportCSV" text="Esporta CSV" />
110 </items>
111 </ContextMenu>
112 </contextMenu>
113 </TableView>
114 </children>
115 </AnchorPane>
116 </items>
117 </SplitPane>
118 </children>
119</fx:root>
120FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("FXMLDocument.fxml"));
121fxmlLoader.setRoot(new AnchorPane());
122Parent root = fxmlLoader.load();
123
Community Discussions contain sources that include Stack Exchange Network
Tutorials and Learning Resources in Datepicker
Tutorials and Learning Resources are not available at this moment for Datepicker