Sfoglia il codice sorgente

اعمال کد تخفیف بر روی دوره ها

hgh 1 anno fa
parent
commit
0e6a8162ae

+ 4 - 1
src/api/models/Classroom.js

@@ -118,10 +118,13 @@ export default class ClassroomAPI extends APIRepository {
     })
   }
 
-  register (id) {
+  register (id, data) {
     return this.sendRequest({
       apiMethod: 'put',
       api: this.api,
+      data: this.getNormalizedSendData({
+        discount_id: null // Number
+      }, data),
       request: this.APIAdresses.register(id),
       resolveCallback: (response) => {
         const data = {

+ 22 - 2
src/api/models/Discount.js

@@ -6,8 +6,9 @@ export default class DiscountAPI extends APIRepository {
   constructor() {
     super('discounts', appApi)
     this.APIAdresses = {
-      base: '/store/discounts',
-      byId: (id) => '/store/discounts/' + id
+      base: '/accounting/discounts',
+      byId: (id) => '/accounting/discounts/' + id,
+      verify: '/accounting/discounts/verify'
     }
     this.CacheList = {
       base: this.name + this.APIAdresses.base
@@ -69,6 +70,25 @@ export default class DiscountAPI extends APIRepository {
     })
   }
 
+  verify (data) {
+    return this.sendRequest({
+      apiMethod: 'post',
+      api: this.api,
+      request: this.APIAdresses.verify,
+      data: this.getNormalizedSendData({
+        code: null, // String
+        target: null, // String
+        target_id: null // Number
+      }, data),
+      resolveCallback: (response) => {
+        return new Discount(response.data)
+      },
+      rejectCallback: (error) => {
+        return error
+      }
+    })
+  }
+
   add (data) {
     return this.sendRequest({
       apiMethod: 'post',

+ 325 - 31
src/components/Widgets/Other/Shop/ShopApplyDiscount/ShopApplyDiscount.vue

@@ -80,36 +80,62 @@
       </div>
     </q-card>
 
-    <q-tab-panels v-model="panel"
-                  animated
-                  class="panels">
-      <q-tab-panel name="userInfo">
-        <q-banner class="banner apply-discount-form-banner">
-          بازبینی
-        </q-banner>
-        <q-card class="apply-discount-form-card">
-          <q-separator />
-        </q-card>
-
-        <div class="flex justify-end section-edit-btn">
-          <q-btn color="primary"
-                 @click="editEntity">
-            تایید و ادامه
-            <svg xmlns="http://www.w3.org/2000/svg"
-                 width="18.387"
-                 height="11.502"
-                 viewBox="0 0 18.387 11.502">
-              <path id="Combined_Shape"
-                    data-name="Combined Shape"
-                    d="M-9.338,11.408a.748.748,0,0,0,.388-.656V6.5h8.2A.751.751,0,0,0,0,5.75.75.75,0,0,0-.75,5h-8.2V.75A.751.751,0,0,0-9.338.093.769.769,0,0,0-9.7,0a.735.735,0,0,0-.4.115l-7.938,5a.747.747,0,0,0-.35.635.742.742,0,0,0,.35.634l7.938,5a.751.751,0,0,0,.4.116A.746.746,0,0,0-9.338,11.408ZM-10.45,9.392l-5.78-3.641,5.78-3.642Z"
-                    transform="translate(18.387)"
-                    fill="#fff" />
-            </svg>
-          </q-btn>
+    <div class="step1">
+      <div class="step1__cart-items">
+        <div class="cart-item">
+          <div class="cart-item__use-type">
+            <q-icon :name="usageIcon" />
+          </div>
+          <div class="cart-item__thumbnail">
+            <q-img :src="classroom.thumbnail" />
+          </div>
+          <div class="cart-item__info">
+            <div class="cart-item__title">
+              {{ classroom.title }}
+            </div>
+            <div class="cart-item__attrs">
+              <div class="cart-item__attr">
+                <div class="cart-item__attr-label">
+                  نوع برگزاری:
+                </div>
+                <div class="cart-item__attr-value">
+                  {{ getHoldingType(classroom.holding_type) }}
+                </div>
+              </div>
+              <div class="cart-item__attr">
+                <div class="cart-item__attr-label">
+                  استاد:
+                </div>
+                <div class="cart-item__attr-value">
+                  {{ classroom.professor_info.firstname }}
+                  {{ classroom.professor_info.lastname }}
+                </div>
+              </div>
+              <div class="cart-item__attr">
+                <div class="cart-item__attr-label">
+                  هزینه برگزاری:
+                </div>
+                <div class="cart-item__attr-value">
+                  {{ classroom.price.toLocaleString('fa') }}
+                  ریال
+                </div>
+              </div>
+            </div>
+            <div class="cart-item__price">
+              <div class="cart-item__price-final" />
+            </div>
+          </div>
         </div>
-      </q-tab-panel>
-
-    </q-tab-panels>
+        <discount :target-id="classroom.id"
+                  :target="'TRAINING'"
+                  @set-discount="setDiscount" />
+      </div>
+      <div class="step1__sidebar">
+        <sidebar :price="classroom.price"
+                 :order-price="orderPrice"
+                 @complete="onComplete" />
+      </div>
+    </div>
 
   </div>
 </template>
@@ -122,10 +148,12 @@ import { APIGateway } from 'src/api/APIGateway.js'
 import { Classroom } from 'src/models/Classroom.js'
 import { AnswerBook } from 'src/models/AnswerBook.js'
 import { FormBuilderAssist } from 'quasar-form-builder'
+import Sidebar from 'components/Widgets/Store/Cart/components/step1/sidebar.vue'
+import Discount from 'components/Widgets/Store/Cart/components/step1/discount.vue'
 
 export default {
   name: 'ShopCompleteInfo',
-  components: { },
+  components: { Discount, Sidebar },
   mixins: [mixinAuth],
   data: () => ({
     mounted: false,
@@ -136,6 +164,8 @@ export default {
     rulesDialog: false,
     loading: true,
     classroom: new Classroom(),
+    discountId: null,
+    orderPrice: 0,
     invoice: new Invoice(),
     eventTestAnswerBook: new AnswerBook(),
 
@@ -168,6 +198,7 @@ export default {
   },
   mounted () {
     this.loadClassroomFromStore()
+    this.orderPrice = this.classroom.price
     if (this.$route.query.source === 'event') {
       this.getEventTest()
     }
@@ -183,6 +214,23 @@ export default {
     })
   },
   methods: {
+    onComplete () {
+      if (this.$route.query.type === 'register') {
+        this.createInvoiceForClassroomOrRegisterEvent()
+      } else {
+        this.$router.push({ name: 'UserPanel.ShopPaymentFromWallet', query: this.$route.query })
+      }
+    },
+    setDiscount (discount) {
+      console.log(discount)
+      if (!discount) {
+        this.orderPrice = this.classroom.price
+        this.discountId = null
+      } else {
+        this.orderPrice = discount.order_price
+        this.discountId = discount.id
+      }
+    },
     getEventTest () {
       if (this.classroom.tests && this.classroom.tests.length === 0) {
         return
@@ -239,7 +287,7 @@ export default {
     register () {
       return new Promise((resolve, reject) => {
         this.invoice.loading = true
-        APIGateway.classroom.register(this.classroom.id)
+        APIGateway.classroom.register(this.classroom.id, { discount_id: this.discountId })
           .then((data) => {
             if (data.type === 'Invoice') {
               this.invoice = new Invoice(data.model)
@@ -403,5 +451,251 @@ export default {
     margin-top: 50px;
     margin-bottom: 77px;
   }
+
+  .step1 {
+  $gap: 28px;
+  display: flex;
+  flex-flow: row;
+  flex-wrap: wrap;
+  gap: $gap;
+  $sidebar-width: 312px;
+  .step1__cart-items {
+    width: calc( 100% - #{$sidebar-width} - #{28px} );
+    display: flex;
+    flex-flow: column;
+    gap: 24px;
+    @media screen and (max-width: 1024px) {
+      & {
+        width: 100%;
+      }
+    }
+
+    .cart-item {
+      $cart-background-color: #F9F9FB;
+      $cart-item__thumbnail-width: 192px;
+      position: relative;
+      background: $cart-background-color;
+      border: 1px solid #DFE1EC;
+      border-radius: 8px;
+      padding: 24px 22px 24px 67px;
+      display: flex;
+      flex-flow: row;
+      flex-wrap: wrap;
+      $gap: 30px;
+      gap: $gap;
+      min-height: 203px;
+
+      .cart-item__use-type {
+        $cart-item__use-type-width: 37px;
+        position: absolute;
+        top: 0;
+        left: 16px;
+        width: $cart-item__use-type-width;
+        color: white;
+        text-align: center;
+        padding-top: 10px;
+        padding-bottom: 22px;
+        background: $primary;
+
+        &:after {
+          position: absolute;
+          content: ' ';
+          bottom: calc((#{$cart-item__use-type-width} * -1 / 2) - 9px);
+          left: 0;
+          transform: rotate(45deg);
+          background: $cart-background-color;
+          width: $cart-item__use-type-width;
+          height: $cart-item__use-type-width;
+          border-radius: 2px;
+        }
+      }
+
+      .cart-item__remove-action {
+        position: absolute;
+        top: 85px;
+        left: 20px;
+
+        .q-btn {
+          width: 32px;
+          height: 32px;
+        }
+
+        @media screen and (max-width: 600px) {
+          & {
+            top: 4px;
+            left: auto;
+            right: 4px;
+          }
+        }
+      }
+
+      .cart-item__thumbnail {
+        width: $cart-item__thumbnail-width;
+        @media screen and (max-width: 600px) {
+          & {
+            width: 100%;
+          }
+        }
+      }
+
+      .cart-item__info {
+        width: calc(100% - #{$cart-item__thumbnail-width} - #{$gap});
+        color: #212121;
+
+        .cart-item__title {
+          font-size: 22px;
+          margin-bottom: 27px;
+        }
+
+        .cart-item__attrs {
+          display: flex;
+          flex-flow: column;
+          gap: 16px;
+          //flex-wrap: nowrap;
+          margin-bottom: 70px;
+
+          .cart-item__attr {
+            display: flex;
+            flex-flow: row;
+            gap: 5px;
+            //flex-wrap: nowrap;
+
+            .cart-item__attr-label {
+              font-size: 16px;
+              color: #797979;
+
+              &:before {
+                display: inline-block;
+                content: ' ';
+                width: 8px;
+                height: 8px;
+                background: #475F4A;
+                border-radius: 100%;
+                margin-right: 4px;
+              }
+            }
+
+            .cart-item__attr-value {
+              font-size: 16px;
+            }
+          }
+
+          @media screen and (max-width: 1200px) {
+            & {
+              flex-flow: column;
+              gap: 8px;
+              margin-bottom: 8px;
+            }
+          }
+        }
+
+        .cart-item__type-info {
+          position: absolute;
+          top: 30px;
+          right: 22px;
+          display: flex;
+          flex-flow: row;
+          align-items: center;
+          justify-content: space-between;
+          gap: 2px;
+          padding: 0 4px 0 16px;
+          background: #FFFFFF;
+          border: 1px solid #DFE1EC;
+          border-radius: 20px;
+          color: #212121;
+          font-size: 16px;
+        }
+
+        .cart-item__count-action {
+          position: absolute;
+          right: 20px;
+          top: 65px;
+          width: 120px;
+          @media screen and (max-width: 1200px) {
+            & {
+              position: relative;
+              top: 0;
+              right: 0;
+              width: 100%;
+            }
+          }
+        }
+
+        .cart-item__price {
+          position: absolute;
+          top: 136px;
+          right: 20px;
+          display: flex;
+          flex-flow: row;
+          align-items: center;
+          justify-content: space-between;
+          gap: 19px;
+
+          .cart-item__price-base {
+            color: #FF3D3D;
+            font-size: 18px;
+            text-decoration: line-through;
+          }
+
+          .cart-item__price-final {
+            color: $primary;
+            font-size: 24px;
+          }
+
+          @media screen and (max-width: 1200px) {
+            & {
+              position: relative;
+              top: 0;
+              right: 0;
+              width: 100%;
+              margin-bottom: 8px;
+            }
+          }
+        }
+
+        .cart-item__products {
+          display: flex;
+          flex-flow: row;
+          flex-wrap: wrap;
+
+          .cart-item__product {
+            width: 33.33%;
+            margin-bottom: 17px;
+
+            &:before {
+              display: inline-block;
+              content: ' ';
+              width: 8px;
+              height: 8px;
+              background: #475F4A;
+              border-radius: 100%;
+              margin-right: 4px;
+            }
+          }
+        }
+
+        @media screen and (max-width: 800px) {
+          & {
+            width: 100%;
+          }
+        }
+      }
+
+      @media screen and (max-width: 600px) {
+        & {
+          padding: 56px 22px 24px 24px;
+        }
+      }
+    }
+  }
+  .step1__sidebar {
+    width: $sidebar-width;
+    @media screen and (max-width: 1024px) {
+      & {
+        width: 100%;
+      }
+    }
+  }
+}
 }
 </style>

+ 23 - 20
src/components/Widgets/Store/Cart/components/step1/discount.vue

@@ -8,11 +8,11 @@
          class="cart-discount__info">
       <div class="cart-discount__selected-discount">
         <q-input v-model="discountCode"
-                 :disable="!!basket.discount"
+                 :disable="!!discount"
                  placeholder="کدتخفیف" />
       </div>
       <div class="cart-discount__edit-btn">
-        <q-btn v-if="!basket.discount"
+        <q-btn v-if="!discount"
                color="info"
                unelevated
                :loading="discountLoading"
@@ -32,28 +32,29 @@
 </template>
 
 <script>
-import { Basket } from 'src/models/Basket.js'
 import { APIGateway } from 'src/api/APIGateway.js'
 
 export default {
   name: 'CartDiscount',
   props: {
-    basket: {
-      type: Basket,
-      default: new Basket()
+    targetId: {
+      type: Number
+    },
+    target: {
+      type: String
     }
   },
   emits: ['set-discount'],
   data () {
     return {
       discountCode: null,
+      discount: null,
       discountLoading: false,
       mounted: false
     }
   },
   mounted() {
     this.mounted = true
-    this.discountCode = this.basket.discount_info.code
   },
   methods: {
     openDialog () {
@@ -64,22 +65,24 @@ export default {
     },
     setDiscount () {
       this.discountLoading = true
-      APIGateway.basket.submitDiscountCode(this.basket.id, this.discountCode)
-        .finally(() => {
-          this.discountLoading = false
-          this.$emit('set-discount')
-        })
+      APIGateway.discount.verify({
+        code: this.discountCode,
+        target: this.target,
+        target_id: this.targetId
+      }).then((discount) => {
+        this.discount = discount
+        this.$emit('set-discount', discount)
+      }
+      ).finally(() => {
+        this.discountLoading = false
+      })
     },
     removeDiscountCode () {
       this.discountLoading = true
-      APIGateway.basket.removeDiscountCode(this.basket.id)
-        .then(() => {
-          this.discountCode = null
-        })
-        .finally(() => {
-          this.discountLoading = false
-          this.$emit('set-discount')
-        })
+      this.discountCode = null
+      this.discount = null
+      this.$emit('set-discount', null)
+      this.discountLoading = false
     }
   }
 }

+ 12 - 31
src/components/Widgets/Store/Cart/components/step1/sidebar.vue

@@ -2,42 +2,20 @@
   <div class="step1__sidebar">
     <div class="step1__sidebar-total-price">
       <div class="step1__sidebar-total-price-label">
-        قیمت کالاها
+        هزینه برگزاری
       </div>
       <div class="step1__sidebar-total-price-value">
-        {{ basket.price.toLocaleString('fa') }}
+        {{ price.toLocaleString('fa') }}
         ریال
       </div>
     </div>
-    <div v-if="basket.margin_amount"
-         class="step1__sidebar-total-discount">
-      <div class="step1__sidebar-total-discount-label">
-        تخفیف ها
-      </div>
-      <div class="step1__sidebar-total-discount-value">
-        {{ basket.margin_amount.toLocaleString('fa') }}
-        ریال
-      </div>
-    </div>
-    <div v-if="basket.margin_amount"
-         class="step1__sidebar-separator" />
-    <div v-if="basket.margin_amount"
-         class="step1__sidebar-total-price">
-      <div class="step1__sidebar-total-price-label">
-        قابل سفارش
-      </div>
-      <div class="step1__sidebar-total-price-value">
-        {{ basket.sellable_price.toLocaleString('fa') }}
-        ریال
-      </div>
-    </div>
-    <div v-if="basket.discount"
+    <div v-if="price!==orderPrice"
          class="step1__sidebar-discount-code">
       <div class="step1__sidebar-discount-code-label">
         کد تخفیف
       </div>
       <div class="step1__sidebar-discount-code-value">
-        {{ basket.discount_amount.toLocaleString('fa') }}
+        {{ (price-orderPrice).toLocaleString('fa') }}
         ریال
       </div>
     </div>
@@ -47,7 +25,7 @@
         مجموع
       </div>
       <div class="step1__sidebar-final-price-value">
-        {{ basket.order_price.toLocaleString('fa') }}
+        {{ orderPrice.toLocaleString('fa') }}
         ریال
       </div>
     </div>
@@ -62,14 +40,17 @@
 </template>
 
 <script>
-import { Basket } from 'src/models/Basket.js'
 
 export default {
   name: 'cartItem',
   props: {
-    basket: {
-      type: Basket,
-      default: new Basket()
+    price: {
+      type: Number,
+      default: 0
+    },
+    orderPrice: {
+      type: Number,
+      default: 0
     }
   },
   emits: ['complete'],

+ 4 - 1
src/models/Classroom.js

@@ -50,7 +50,10 @@ class Classroom extends Model {
         relatedModel: SessionList
       },
       { key: 'audience_role' },
-      { key: 'price' },
+      {
+        key: 'price',
+        default: 0
+      },
       { key: 'codes' },
       { key: 'capacity' },
       { key: 'used_capacity' },

+ 14 - 1
src/models/Discount.js

@@ -5,12 +5,25 @@ class Discount extends Model {
     super(data, [
       { key: 'id' },
       { key: 'code' },
+      { key: 'price' },
+      { key: 'order_price' },
+      { key: 'target' },
       {
         key: 'percent',
         default: 0
       },
       { key: 'expire_time' }
-    ])
+    ], {
+      status: {
+        infoKey: 'target_info',
+        enumListKey: 'targetEnums',
+        enums: [
+          { label: 'فروشگاه', value: 'STORE' },
+          { label: 'دوره آموزشی', value: 'TRAINING' },
+          { label: 'رویداد', value: 'EVENT' }
+        ]
+      }
+    })
   }
 }