RateDetail.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. <template>
  2. <div class="container">
  3. <el-form
  4. ref="form"
  5. :model="form"
  6. :rules="rules"
  7. label-width="150px"
  8. label-position="top">
  9. <div class="content">
  10. <div class="section-title">Rate Config</div>
  11. <div class="flexcr">
  12. <el-form-item
  13. label="Name:"
  14. prop="rateName"
  15. class="add-input">
  16. <el-input
  17. v-model="form.rateName"/>
  18. </el-form-item>
  19. <el-form-item
  20. label="Country:"
  21. prop="countryCode"
  22. class="add-input">
  23. <el-select
  24. v-model="form.countryCode">
  25. <el-option
  26. v-for="item in options.country"
  27. :key="item.name"
  28. :label="item.name"
  29. :value="item.value" />
  30. </el-select>
  31. </el-form-item>
  32. <!-- <el-form-item
  33. label="Rate Type:"
  34. prop="rateType"
  35. class="add-input">
  36. <el-input
  37. v-model="form.rateType"/>
  38. </el-form-item> -->
  39. </div>
  40. <div class="flexcr">
  41. <label class="el-form-item__label">Repeat:</label>
  42. <div class="repeat-view">
  43. (&nbsp;
  44. <div
  45. class="link-type"
  46. v-for="(item, index) in options.shortcut"
  47. :key="index"
  48. @click="handleShortcut(item)">
  49. <span>{{item.name}}</span>
  50. </div>
  51. &nbsp;)
  52. <el-tooltip
  53. effect="dark"
  54. content="This is an items for quickly selecting the repeats"
  55. placement="right">
  56. <i class="el-icon-question icon-help"></i>
  57. </el-tooltip>
  58. </div>
  59. </div>
  60. <div style="margin-bottom: 10px;">
  61. <el-checkbox-group
  62. v-model="form.repeats">
  63. <el-checkbox-button
  64. v-for="(item, index) in options.repeat"
  65. :label="item.value"
  66. :key="index">
  67. {{item.name}}
  68. </el-checkbox-button>
  69. </el-checkbox-group>
  70. </div>
  71. <div class="flexcr">
  72. <el-form-item
  73. label="All Day:"
  74. class="add-input">
  75. <el-switch
  76. v-model="form.allDay"
  77. @change="changeAllday"/>
  78. </el-form-item>
  79. <template v-if="form.allDay">
  80. <el-form-item
  81. label="Start Time:"
  82. class="add-input">
  83. <el-input disabled/>
  84. </el-form-item>
  85. <el-form-item
  86. label="End Time:"
  87. class="add-input">
  88. <el-input disabled/>
  89. </el-form-item>
  90. </template>
  91. <template v-else>
  92. <el-form-item
  93. label="Start Time:"
  94. class="add-input"
  95. prop="startTime">
  96. <el-time-picker
  97. v-model="form.startTime"
  98. format="HH:mm"
  99. value-format="HH:mm"
  100. clearable/>
  101. </el-form-item>
  102. <el-form-item
  103. label="End Time:"
  104. class="add-input"
  105. prop="endTime">
  106. <el-time-picker
  107. v-model="form.endTime"
  108. format="HH:mm"
  109. value-format="HH:mm"
  110. clearable/>
  111. </el-form-item>
  112. </template>
  113. </div>
  114. </div>
  115. <div class="content">
  116. <div class="section-title flexcr">
  117. CHARGE SITE RATE
  118. <div class="section-sub-title">(Currency Used: {{currencyData[form.countryCode]}})</div>
  119. </div>
  120. <charge-rate
  121. v-model="ratesForm.chargeRates"/>
  122. </div>
  123. <div class="content" v-if="false">
  124. <div class="section-title flexcr">
  125. SPECIAL CHARGE RATE
  126. <div class="section-sub-title">(Currency Used: {{currencyData[form.countryCode]}})</div>
  127. </div>
  128. <charge-rate
  129. isSpecial
  130. v-model="ratesForm.specialChargeRates"/>
  131. </div>
  132. <div class="content flexcr">
  133. <div class="buttons">
  134. <el-button
  135. @click="onBack"
  136. type="primary"
  137. class="cancel-button">
  138. Cancel
  139. </el-button>
  140. <el-button
  141. @click="onClickSave"
  142. type="primary"
  143. :loading="loadingSave">
  144. &nbsp;Save&nbsp;
  145. </el-button>
  146. </div>
  147. <div class="update-by" v-if="isEdit">
  148. <span
  149. class="add-text"
  150. :title='"CREATED BY " + form.createdBy + " ON " + form.createdOn'>
  151. LAST UPDATED BY {{form.updatedBy}} TIMESTAMP: {{form.updatedOn}}
  152. </span>
  153. </div>
  154. </div>
  155. </el-form>
  156. </div>
  157. </template>
  158. <script>
  159. import site from '../../http/api/site'
  160. import api from '../../http/api/rates'
  161. import settings from '../../settings.js'
  162. import ChargeRate from './components/ChargeRate'
  163. export default {
  164. data() {
  165. return {
  166. loading: false,
  167. loadingSave: false,
  168. isEdit: false,
  169. form: {
  170. dynamicRateId: "",
  171. rateName: "",
  172. countryCode: settings.defaultCountry,
  173. repeats: [],
  174. allDay: false,
  175. startTime: "",
  176. endTime: "",
  177. rates: [],
  178. specialRates: []
  179. },
  180. options: {
  181. country: [],
  182. repeat: [],
  183. shortcut: [{
  184. name: "Daily",
  185. value: [],
  186. all: true
  187. },{
  188. name: "Weekday",
  189. value: ["Mon","Tue","Wed","Thu","Fri"]
  190. },{
  191. name: "Weekend",
  192. value: ["Sat","Sun"]
  193. }, {
  194. name: "None",
  195. value: []
  196. }]
  197. },
  198. currencyData: {
  199. SG: "S$"
  200. },
  201. ratesForm: {
  202. chargeRates: [{
  203. rate: '',
  204. rateType: '',
  205. chargeTypePk: '',
  206. dynamicRateItemId: ''
  207. }],
  208. specialChargeRates: [{
  209. rate: '',
  210. rateType: '',
  211. chargeTypePk: '',
  212. groupPk: ''
  213. }]
  214. },
  215. rules: {
  216. rateName: {
  217. required: true,
  218. trigger: "blur",
  219. message: "Please input rate name"
  220. },
  221. startTime: {
  222. required: true,
  223. trigger: "change",
  224. message: "Please select start time"
  225. },
  226. endTime: {
  227. required: true,
  228. trigger: "change",
  229. message: "Please select end time"
  230. }
  231. },
  232. }
  233. },
  234. components: {ChargeRate},
  235. created() {
  236. this.loading = true;
  237. this.getCountryOptions();
  238. this.getRepeatOptions();
  239. if (this.$route.params.id) {
  240. this.isEdit = true;
  241. this.getRateDetail();
  242. }
  243. },
  244. methods: {
  245. onBack() {
  246. this.$nextTick(() => {
  247. this.$router.replace({
  248. path: "/site-management/dynamic-rate-configuration"
  249. })
  250. })
  251. },
  252. getCountryOptions() {
  253. site.getCountryList().then(res => {
  254. if (res.data) {
  255. this.options.country = res.data
  256. const sign = {}
  257. res.data.forEach(item => {
  258. sign[item.value] = item.currencySymbol
  259. })
  260. this.currencyData = sign;
  261. }
  262. }).catch(err => {
  263. this.$message({
  264. type: 'error',
  265. message: err
  266. })
  267. this.loading = false;
  268. })
  269. },
  270. getRepeatOptions() {
  271. api.getRepeatOptions().then(res => {
  272. if (res.data) {
  273. this.options.repeat = res.data
  274. }
  275. }).catch(err => {
  276. this.$message({
  277. type: 'error',
  278. message: err
  279. })
  280. }).finally(() => {
  281. this.loading = false;
  282. })
  283. },
  284. getRateDetail() {
  285. this.loading = true;
  286. api.getDynamicRateInfo({
  287. dynamicRateId: this.$route.params.id
  288. }).then(res => {
  289. if (res.data) {
  290. this.form = res.data;
  291. if (res.data.rates && res.data.rates.length) {
  292. this.ratesForm.chargeRates = res.data.rates;
  293. }
  294. }
  295. }).catch(err => {
  296. this.$message({
  297. type: 'error',
  298. message: err
  299. })
  300. }).finally(() => {
  301. this.loading = false;
  302. })
  303. },
  304. handleShortcut(shortcut) {
  305. const select = []
  306. if (shortcut.all) {
  307. this.options.repeat.forEach(item => {
  308. select.push(item.value)
  309. })
  310. } else {
  311. select.push(...shortcut.value)
  312. }
  313. this.form.repeats = select;
  314. },
  315. changeAllday(all) {
  316. if (all) {
  317. this.form.startTime = "";
  318. this.form.endTime = "";
  319. this.$refs.form.clearValidate()
  320. }
  321. },
  322. onClickSave() {
  323. this.$refs.form.validate(result => {
  324. if (result) {
  325. if (this.form.repeats.length == 0) {
  326. this.$message({
  327. message: "Please select at least one repeat day",
  328. type: 'error',
  329. duration: 3000,
  330. })
  331. return;
  332. }
  333. const rates = [];
  334. this.ratesForm.chargeRates.forEach(item => {
  335. if (item.rate) {
  336. rates.push(item);
  337. }
  338. })
  339. this.ratesForm.specialChargeRates.forEach(item => {
  340. if (item.rate) {
  341. rates.push(item);
  342. }
  343. })
  344. if (rates.length == 0) {
  345. this.$message({
  346. message: "Please add at least one site rate",
  347. type: 'error',
  348. duration: 3000,
  349. })
  350. return;
  351. }
  352. this.form.rates = rates;
  353. this.loadingSave = true;
  354. this.isEdit ? this.updateRateData() : this.addRateData();
  355. }
  356. });
  357. },
  358. addRateData() {
  359. api.addDynamicRate(this.form).then(res => {
  360. this.$message({
  361. type: 'success',
  362. message: "Successfully added"
  363. });
  364. this.onBack();
  365. }).catch(err => {
  366. this.$message({
  367. type: 'error',
  368. message: err
  369. });
  370. }).finally(() => {
  371. this.loadingSave = false;
  372. });
  373. },
  374. updateRateData() {
  375. api.updateDynamicRate(this.form).then(res => {
  376. this.$message({
  377. type: 'success',
  378. message: "Successfully updated"
  379. });
  380. this.onBack();
  381. }).catch(err => {
  382. this.$message({
  383. type: 'error',
  384. message: err
  385. });
  386. }).finally(() => {
  387. this.loadingSave = false;
  388. });
  389. }
  390. }
  391. }
  392. </script>
  393. <style lang="scss" scoped>
  394. @import '../../styles/variables.scss';
  395. .container {
  396. width: 100%;
  397. padding: 20px 60px;
  398. min-height: $mainAppMinHeight;
  399. background-color: #F0F5FC;
  400. }
  401. .content {
  402. margin: 0 8px 16px;
  403. padding: 15px 80px;
  404. border-radius: 6px;
  405. background-color: white;
  406. }
  407. .section-title {
  408. color: #333;
  409. margin-top: 20px;
  410. margin-bottom: 30px;
  411. font-size: 15px;
  412. user-select: none;
  413. line-height: 24px;
  414. font-weight: bold;
  415. font-family: sans-serif;
  416. text-transform: uppercase;
  417. }
  418. .section-sub-title {
  419. font-size: 14px;
  420. padding-left: 5px;
  421. font-weight: normal;
  422. }
  423. .add-text {
  424. width: 100%;
  425. min-width: 100px;
  426. max-width: 300px;
  427. }
  428. .add-text ::v-deep .el-textarea__inner {
  429. font-family: sans-serif;
  430. }
  431. .add-input {
  432. width: 100%;
  433. min-width: 100px;
  434. max-width: 250px;
  435. margin-right: 10px;
  436. ::v-deep .el-input,
  437. ::v-deep .el-select {
  438. width: 100%;
  439. }
  440. }
  441. .icon-help {
  442. color: #999;
  443. font-size: 15px;
  444. cursor: pointer;
  445. }
  446. .form-photo {
  447. flex: 1;
  448. ::v-deep .el-form-item__label {
  449. padding: 12px;
  450. line-height: 16px;
  451. }
  452. .photo-uploader {
  453. margin-right: 10px;
  454. .uploader-image {
  455. width: 180px;
  456. height: 120px;
  457. text-align: left;
  458. }
  459. ::v-deep img {
  460. object-fit: cover;
  461. }
  462. .avatar-uploader-icon {
  463. border: 1px dashed #d9d9d9;
  464. border-radius: 6px;
  465. cursor: pointer;
  466. font-size: 28px;
  467. color: #8c939d;
  468. width: 120px;
  469. height: 120px;
  470. line-height: 120px;
  471. text-align: center;
  472. }
  473. }
  474. }
  475. .repeat-view {
  476. display: flex;
  477. font-size: 14px;
  478. font-weight: bold;
  479. align-items: center;
  480. padding: 0 10px 10px;
  481. .link-type + .link-type {
  482. margin-left: 5px;
  483. &::before {
  484. color: #333;
  485. content: "|";
  486. font-size: 15px;
  487. font-weight: normal;
  488. padding-right: 5px;
  489. }
  490. }
  491. }
  492. .hr {
  493. height: 2px;
  494. margin: 10px -40px;
  495. background-color: #F0F5FC;
  496. }
  497. .buttons {
  498. padding-top: 15px;
  499. padding-bottom: 15px;
  500. }
  501. @media screen and (max-width: 1200px) {
  502. .add-input {
  503. min-width: 80px;
  504. max-width: 200px;
  505. }
  506. }
  507. @media screen and (max-width: 500px) {
  508. .container {
  509. padding: 0px;
  510. }
  511. .content {
  512. padding: 15px 30px;
  513. }
  514. .add-input {
  515. max-width: unset;
  516. }
  517. }
  518. </style>