You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

propertyCreate.vue 21KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607
  1. <template>
  2. <!-- eslint-disable max-len -->
  3. <div>
  4. <div class="container">
  5. <div class="col-sm-12">
  6. <br />
  7. <div class="tobuy-img-box">
  8. <img
  9. v-if="propertyType === 'Commercial'"
  10. src="img/Commercial-Property.jpg"
  11. alt="Timeshare To Buy"
  12. class="img-fluid"
  13. style="width:800px;height:400px; border-radius:10px"
  14. />
  15. <img
  16. v-else
  17. src="img/Listing3.2.jpg"
  18. alt="Timeshare To Buy"
  19. class="img-fluid"
  20. style="width:800px;height:400px; border-radius:10px"
  21. />
  22. </div>
  23. <div class="sinse-box" style="opacity:0.7; border: white solid 3px; border-radius: 15px">
  24. <h3 class="sinse-title">List {{ propertyType }} {{ salesType }} Property</h3>
  25. </div>
  26. </div>
  27. <br />
  28. <div class="row">
  29. <div class="container col-md-10">
  30. <div class="title-box-d">
  31. <h5 class="title-d" style="text-align:left">Property Overview</h5>
  32. </div>
  33. </div>
  34. </div>
  35. <div class="row mb-3">
  36. <div class="container col-md-10" style="text-align:left">
  37. <form id="mainForm">
  38. <div class="form-goup row">
  39. <div class="col-md-4">
  40. <label>Usage Type</label>
  41. <div class="input-group-prepend">
  42. <span class="input-group-text" style="color: #60CBEB">
  43. <b>U</b>
  44. </span>
  45. <select
  46. class="form-control"
  47. name="propertyUsageType"
  48. id="propertyUsageType"
  49. v-model="propertyType"
  50. @change="TypeChanged"
  51. >
  52. <option value="Residential">Residential</option>
  53. <option value="Commercial">Commercial</option>
  54. </select>
  55. </div>
  56. </div>
  57. </div>
  58. <br />
  59. <div class="form-group row">
  60. <div class="col-md-4">
  61. <label>Property Type *</label>
  62. <div class="input-group-prepend">
  63. <span class="input-group-text" style="color: #60CBEB">
  64. <b>T</b>
  65. </span>
  66. <select
  67. class="form-control"
  68. name="propertyType"
  69. id="propertyType"
  70. v-model="property.propertyTypeId"
  71. @change="PropertyTypeSelected"
  72. >
  73. <option value="0">Please select type</option>
  74. <option v-for="item in propertyTypes" :value="item.id" :key="item.id">{{
  75. item.description
  76. }}</option>
  77. </select>
  78. </div>
  79. <div v-if="showPropertyTypeError">
  80. <p class="alert myError">Please select a type</p>
  81. </div>
  82. </div>
  83. <div v-if="propertyType === 'Commercial'" class="col-md-4">
  84. <label>Property Name</label>
  85. <div class="input-group-prepend">
  86. <span class="input-group-text" style="color: #60CBEB">
  87. <b>N</b>
  88. </span>
  89. <input
  90. class="form-control"
  91. type="text"
  92. name="propertyName"
  93. id="propertyName"
  94. v-model="property.propertyName"
  95. />
  96. </div>
  97. </div>
  98. <div v-if="propertyType === 'Commercial'" class="col-md-4">
  99. <label>Unit</label>
  100. <div class="input-group-prepend">
  101. <span class="input-group-text" style="color: #60CBEB">
  102. <b>U#</b>
  103. </span>
  104. <input
  105. class="form-control"
  106. type="text"
  107. name="unit"
  108. id="unit"
  109. v-model="property.unit"
  110. />
  111. </div>
  112. </div>
  113. </div>
  114. <div class="form-group row">
  115. <div class="col-md-6" style="margin-bottom: 1em">
  116. <label>Street Number</label>
  117. <div class="input-group-prepend">
  118. <span class="input-group-text">
  119. <eva-icon name="home-outline" fill="#60CBEB"></eva-icon>
  120. </span>
  121. <input
  122. class="form-control"
  123. type="text"
  124. name="streetnumber"
  125. v-model="property.addressLine1"
  126. />
  127. </div>
  128. </div>
  129. <div class="col-md-6" style="margin-bottom: 1em">
  130. <label>Street Name</label>
  131. <div class="input-group-prepend">
  132. <span class="input-group-text">
  133. <eva-icon name="home-outline" fill="#60CBEB"></eva-icon>
  134. </span>
  135. <input
  136. class="form-control"
  137. type="text"
  138. name="streetname"
  139. id="streetname"
  140. v-model="property.addressLine2"
  141. />
  142. </div>
  143. </div>
  144. <div class="col-md-6" style="margin-bottom: 1em">
  145. <label>Province *</label>
  146. <div class="input-group-prepend">
  147. <span class="input-group-text">
  148. <eva-icon name="home-outline" fill="#60CBEB"></eva-icon>
  149. </span>
  150. <select
  151. class="form-control"
  152. name="propertyType"
  153. id="propertyType"
  154. @change="ProvinceSelected"
  155. v-model="property.provinceId"
  156. >
  157. <option value="0">Please select province</option>
  158. <option v-for="province in provinces" :value="province.id" :key="province.id">{{
  159. province.description
  160. }}</option>
  161. </select>
  162. </div>
  163. <div v-if="showProvinceError">
  164. <p class="alert myError">Please select a Province</p>
  165. </div>
  166. </div>
  167. <div class="col-md-6" style="margin-bottom: 1em">
  168. <label>City *</label>
  169. <div class="input-group-prepend">
  170. <span class="input-group-text">
  171. <eva-icon name="home-outline" fill="#60CBEB"></eva-icon>
  172. </span>
  173. <select
  174. class="form-control"
  175. name="propertyType"
  176. id="propertyType"
  177. @change="CitySelected"
  178. v-model="property.cityId"
  179. >
  180. <option value="0">Please select city</option>
  181. <option v-for="city in cities" :value="city.id" :key="city.id">{{
  182. city.description
  183. }}</option>
  184. </select>
  185. </div>
  186. <div v-if="showCityError">
  187. <p class="alert myError">Please select a City</p>
  188. </div>
  189. </div>
  190. <div class="col-md-6" style="margin-bottom: 1em">
  191. <label>Suburb *</label>
  192. <div class="input-group-prepend">
  193. <span class="input-group-text">
  194. <eva-icon name="home-outline" fill="#60CBEB"></eva-icon>
  195. </span>
  196. <select
  197. class="form-control"
  198. name="propertyType"
  199. id="suburbselector"
  200. v-model="property.suburbId"
  201. @change="getPostalCode"
  202. >
  203. <option value="0">Please select suburb</option>
  204. <option v-for="suburb in suburbs" :value="suburb.id" :key="suburb.id">{{
  205. suburb.description
  206. }}</option>
  207. </select>
  208. </div>
  209. <div v-if="showSuburbError">
  210. <p class="alert myError">Please select a Suburb</p>
  211. </div>
  212. </div>
  213. <div class="col-md-6" style="margin-bottom: 1em">
  214. <label>Postal Code</label>
  215. <div class="input-group-prepend">
  216. <span class="input-group-text">
  217. <eva-icon name="home-outline" fill="#60CBEB"></eva-icon>
  218. </span>
  219. <input
  220. class="form-control"
  221. type="text"
  222. name="postalcode"
  223. v-model="property.addressLine3"
  224. />
  225. </div>
  226. </div>
  227. </div>
  228. <div class="form-group row">
  229. <div class="col-md-6">
  230. <label v-if="salesType === 'Rental'">Rental Price</label>
  231. <label v-if="salesType !== 'Rental'">Sales Price</label>
  232. <div class="input-group-prepend">
  233. <span class="input-group-text" style="color: #60CBEB">
  234. <b>R</b>
  235. </span>
  236. <input
  237. class="form-control"
  238. type="number"
  239. name="price"
  240. id="price"
  241. placeholder="R"
  242. v-model="property.price"
  243. />
  244. </div>
  245. </div>
  246. <div class="col-md-6" v-if="salesType === 'Rental'">
  247. <label>Per</label>
  248. <div class="input-group-prepend">
  249. <span class="input-group-text" style="color: #60CBEB">
  250. <b>D/M</b>
  251. </span>
  252. <select
  253. class="form-control"
  254. name="propertyType"
  255. id="propertyType"
  256. v-model="property.pricePer"
  257. >
  258. <option value>Please select</option>
  259. <option value="Month">Month</option>
  260. <option value="Day">Day</option>
  261. </select>
  262. </div>
  263. </div>
  264. </div>
  265. <div class="form-group row">
  266. <div class="col-md-12">
  267. <label for="Property Description">Description</label>
  268. <vue-editor v-model="property.description" :editor-toolbar="customToolbar" />
  269. <br />
  270. <p>
  271. * A listing fee of R380 including VAT is payable to list your Property on the
  272. Uni-Vate website
  273. </p>
  274. </div>
  275. </div>
  276. <div class="form-group row" />
  277. <UserField
  278. v-if="(propertyType === 'Residential') & (propertyOverviewFields.length > 0)"
  279. :fields="propertyOverviewFields[0].fields"
  280. @UpdateUserDefinedFields="UpdateUserDefinedFields"
  281. :id="1"
  282. ></UserField>
  283. <div class="form-group row" />
  284. <div v-for="item in propertyFields" :key="item.id">
  285. <div class="row">
  286. <div class="col-sm-12">
  287. <div class="title-box-d">
  288. <h5 class="title-d">{{ item.name }}</h5>
  289. </div>
  290. </div>
  291. </div>
  292. <UserField
  293. :fields="item.fields"
  294. :id="item.name"
  295. @UpdateUserDefinedFields="UpdateUserDefinedFields"
  296. :fieldValues="item.fields"
  297. />
  298. </div>
  299. <div class="form-group row" />
  300. <div class="row">
  301. <div class="col-sm-12">
  302. <div class="title-box-d">
  303. <h5 class="title-d">Media</h5>
  304. </div>
  305. </div>
  306. </div>
  307. <div class="form-group row">
  308. <div class="col-md-12">
  309. <label>Virtual Tour (URL)</label>
  310. <div class="input-group-prepend">
  311. <span class="input-group-text" style="color: #60CBEB">
  312. <b>VT</b>
  313. </span>
  314. <input
  315. class="form-control"
  316. type="link"
  317. name="vtlink"
  318. id="vtlink"
  319. v-model="property.virtualTour"
  320. />
  321. </div>
  322. </div>
  323. </div>
  324. <div class="form-group row">
  325. <div class="col-md-12">
  326. <label>Video (URL)</label>
  327. <div class="input-group-prepend">
  328. <span class="input-group-text" style="color: #60CBEB">
  329. <b>V</b>
  330. </span>
  331. <input
  332. class="form-control"
  333. type="link"
  334. name="vlink"
  335. id="vlink"
  336. v-model="property.video"
  337. />
  338. </div>
  339. </div>
  340. </div>
  341. <div class="form-group row">
  342. <div class="col-md-6">
  343. <label>Images</label>
  344. <div class="input-group-prepend"></div>
  345. </div>
  346. </div>
  347. <ImageLoad
  348. :loadedImages="loadedImages"
  349. :savedImages="propertyImages"
  350. @DefaultImage="UpdateDefaultImage"
  351. />
  352. <button
  353. v-if="!wait"
  354. type="button"
  355. @click="SubmitData()"
  356. class="btn btn-b-n"
  357. style="width: 85px; height:40px;"
  358. >
  359. Save
  360. </button>
  361. <div
  362. v-if="showPropertyTypeError || showProvinceError || showCityError || showSuburbError"
  363. >
  364. <p class="alert myError">
  365. Missing fields. Please fill in all required fields. Marked with *
  366. </p>
  367. </div>
  368. <div v-if="wait" id="preloader"></div>
  369. </form>
  370. </div>
  371. </div>
  372. </div>
  373. </div>
  374. </template>
  375. <script>
  376. import { mapState, mapActions } from 'vuex';
  377. import { VueEditor } from 'vue2-editor';
  378. import UserField from './propertyUserField.vue';
  379. import ImageLoad from './propertyImage.vue';
  380. export default {
  381. name: 'PropertyCreate',
  382. components: {
  383. UserField,
  384. ImageLoad,
  385. VueEditor,
  386. },
  387. data() {
  388. return {
  389. propertyType: 'Residential',
  390. salesType: 'Rental',
  391. selectedProvince: '',
  392. selectedCity: '',
  393. images: [],
  394. propertyFieldValues: [],
  395. defaultImage: 0,
  396. wait: false,
  397. customToolbar: [
  398. [{ header: [false, 1, 2, 3, 4, 5, 6] }],
  399. ['bold', 'italic', 'underline', 'strike'],
  400. [{ align: '' }, { align: 'center' }, { align: 'right' }, { align: 'justify' }],
  401. [{ list: 'ordered' }, { list: 'bullet' }, { list: 'check' }],
  402. [{ script: 'sub' }, { script: 'super' }],
  403. [{ indent: '-1' }, { indent: '+1' }],
  404. ],
  405. error: '',
  406. showPropertyTypeError: false,
  407. showProvinceError: false,
  408. showCityError: false,
  409. showSuburbError: false,
  410. };
  411. },
  412. methods: {
  413. ...mapActions('searchTab', ['getProvince', 'getCities', 'getSuburbs']),
  414. ...mapActions('property', [
  415. 'getPropertyTypes',
  416. 'getPropertyOverviewFields',
  417. 'getPropertyFields',
  418. 'saveProperty',
  419. 'getProperty',
  420. 'getPropertyImages',
  421. 'clearProperty',
  422. 'clearPropertyImages',
  423. 'getPropertyEditDisplay',
  424. 'getPropertySavedOverviewFields',
  425. 'getPropertySavedFields',
  426. 'getSavedPropertyData',
  427. ]),
  428. TypeChanged() {
  429. this.propertyType = this.property.propertyUsageType;
  430. },
  431. SubmitData() {
  432. if (this.property.propertyTypeId === 0) {
  433. this.showPropertyTypeError = true;
  434. }
  435. if (this.property.provinceId === 0) {
  436. this.showProvinceError = true;
  437. }
  438. if (this.property.cityId === 0) {
  439. this.showCityError = true;
  440. }
  441. if (this.property.suburbId === 0) {
  442. this.showSuburbError = true;
  443. }
  444. if (
  445. this.showPropertyTypeError
  446. || this.showProvinceError
  447. || this.showCityError
  448. || this.showSuburbError
  449. ) {
  450. return;
  451. }
  452. this.wait = true;
  453. if (this.salesType === 'Sale') {
  454. this.property.isSale = true;
  455. }
  456. // eslint-disable-next-line no-plusplus
  457. for (let i = 0; i < this.images.length; i++) {
  458. let setAsDefault = false;
  459. if (i === this.defaultImage) {
  460. setAsDefault = true;
  461. }
  462. this.property.propertyImages.push({
  463. image: this.images[i],
  464. isDefault: setAsDefault,
  465. });
  466. }
  467. this.property.propertyUserFields = this.propertyFieldValues;
  468. if (this.user) {
  469. this.property.userId = this.user.id;
  470. }
  471. this.saveProperty(this.property)
  472. .then((fulfilled) => {
  473. this.$router.push(`/property/property/${fulfilled.data.id}`);
  474. })
  475. .catch((error) => {
  476. console.log(error.message);
  477. });
  478. },
  479. Close() {
  480. this.$router.push('/property/admin/list/my');
  481. },
  482. PropertyTypeSelected(item) {
  483. if (item.target.options.selectedIndex > 0) {
  484. this.showPropertyTypeError = false;
  485. } else {
  486. this.showPropertyTypeError = true;
  487. }
  488. },
  489. ProvinceSelected(item) {
  490. if (item.target.options.selectedIndex > 0) {
  491. this.selectedProvince = this.provinces[item.target.options.selectedIndex - 1].description;
  492. this.getCities(Object.assign({}, { province: this.selectedProvince }));
  493. this.showProvinceError = false;
  494. } else {
  495. this.showProvinceError = true;
  496. }
  497. },
  498. CitySelected(item) {
  499. if (item.target.options.selectedIndex > 0) {
  500. this.selectedCity = this.cities[item.target.options.selectedIndex - 1].description;
  501. this.getSuburbs(
  502. Object.assign({}, { province: this.selectedProvince, city: this.selectedCity }),
  503. );
  504. this.showCityError = false;
  505. } else {
  506. this.showCityError = true;
  507. }
  508. },
  509. getPostalCode(item) {
  510. this.property.addressLine3 = this.suburbs[item.target.options.selectedIndex - 1].postalCode;
  511. if (item.target.options.selectedIndex > 0) {
  512. this.showSuburbError = false;
  513. } else {
  514. this.showSuburbError = true;
  515. }
  516. },
  517. loadedImages(values) {
  518. this.images = values;
  519. },
  520. UpdateUserDefinedFields(item) {
  521. let update = false;
  522. this.propertyFieldValues.forEach((element) => {
  523. if (element.userDefinedFieldId === item.userDefinedFieldId) {
  524. element.value = item.value;
  525. update = true;
  526. }
  527. });
  528. if (!update) {
  529. this.propertyFieldValues.push(item);
  530. }
  531. },
  532. UpdateDefaultImage(item) {
  533. this.defaultImage = item;
  534. },
  535. },
  536. mounted() {
  537. this.wait = false;
  538. this.clearProperty();
  539. this.clearPropertyImages();
  540. this.images = [];
  541. this.defaultImage = 0;
  542. if (this.propertyOverviewFields.length > 0) {
  543. this.propertyOverviewFields = [];
  544. }
  545. if (this.propertyFields.length > 0) {
  546. this.propertyFields = [];
  547. }
  548. if (this.property.description !== '') {
  549. this.property.description = '';
  550. }
  551. if (this.$route.params.propertyUsageType) {
  552. this.propertyType = this.$route.params.propertyUsageType;
  553. }
  554. this.salesType = this.$route.params.saleType;
  555. this.getPropertyTypes(this.propertyType);
  556. this.getProvince();
  557. this.getPropertyOverviewFields();
  558. this.getPropertyFields(this.propertyType);
  559. },
  560. computed: {
  561. ...mapState('searchTab', ['provinces', 'cities', 'suburbs']),
  562. ...mapState('property', [
  563. 'propertyTypes',
  564. 'propertyOverviewFields',
  565. 'propertyFields',
  566. 'property',
  567. 'propertyImages',
  568. ]),
  569. ...mapState('authentication', ['user']),
  570. SalesTypeChanged() {
  571. // eslint-disable-next-line vue/no-side-effects-in-computed-properties
  572. // this.propertyType = this.$route.params.propType;
  573. // eslint-disable-next-line vue/no-side-effects-in-computed-properties
  574. this.salesType = this.$route.params.saleType;
  575. if (this.property && this.property.propertyUsageType) {
  576. // eslint-disable-next-line vue/no-side-effects-in-computed-properties
  577. this.propertyType = this.property.propertyUsageType;
  578. }
  579. if (!this.$route.query.id) {
  580. this.getPropertyFields(this.propertyType);
  581. }
  582. this.getPropertyTypes(this.propertyType);
  583. return this.propertyType;
  584. },
  585. },
  586. watch: {
  587. SalesTypeChanged() {
  588. return null;
  589. },
  590. },
  591. };
  592. </script>