Compare commits
2 commits
51e9418e54
...
aba67ec177
| Author | SHA1 | Date | |
|---|---|---|---|
| aba67ec177 | |||
| 69c224722e |
6 changed files with 215 additions and 56 deletions
|
|
@ -103,7 +103,7 @@ const encodedCompanyAddress = computed(() => {
|
||||||
gap: 14px;
|
gap: 14px;
|
||||||
|
|
||||||
& h6 {
|
& h6 {
|
||||||
color: $link_primary;
|
color: #d2d0d0;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
letter-spacing: -0.5px;
|
letter-spacing: -0.5px;
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,12 @@ export function useOrderBuy() {
|
||||||
|
|
||||||
const { mutate, loading, error } = useMutation<IBuyOrderResponse>(BUY_CART);
|
const { mutate, loading, error } = useMutation<IBuyOrderResponse>(BUY_CART);
|
||||||
|
|
||||||
async function buyOrder() {
|
async function buyOrder(promocodeUuid?: string) {
|
||||||
const result = await mutate({
|
const result = await mutate({
|
||||||
orderUuid: orderUuid.value,
|
orderUuid: orderUuid.value,
|
||||||
forcePayment: true,
|
forcePayment: true,
|
||||||
|
forceBalance: false,
|
||||||
|
promocodeUuid: promocodeUuid
|
||||||
});
|
});
|
||||||
|
|
||||||
if (result?.data?.buyOrder?.transaction?.process?.url) {
|
if (result?.data?.buyOrder?.transaction?.process?.url) {
|
||||||
|
|
|
||||||
|
|
@ -88,11 +88,15 @@ export const BULK_CART = gql`
|
||||||
export const BUY_CART = gql`
|
export const BUY_CART = gql`
|
||||||
mutation buyOrder(
|
mutation buyOrder(
|
||||||
$orderUuid: String!,
|
$orderUuid: String!,
|
||||||
$forcePayment: Boolean!
|
$forcePayment: Boolean,
|
||||||
|
$forceBalance: Boolean,
|
||||||
|
$promocodeUuid: String,
|
||||||
) {
|
) {
|
||||||
buyOrder(
|
buyOrder(
|
||||||
orderUuid: $orderUuid
|
orderUuid: $orderUuid
|
||||||
forcePayment: $forcePayment
|
forcePayment: $forcePayment
|
||||||
|
forceBalance: $forceBalance
|
||||||
|
promocodeUuid: $promocodeUuid
|
||||||
) {
|
) {
|
||||||
transaction {
|
transaction {
|
||||||
amount
|
amount
|
||||||
|
|
|
||||||
|
|
@ -2,23 +2,8 @@
|
||||||
<div class="cart">
|
<div class="cart">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="cart__wrapper">
|
<div class="cart__wrapper">
|
||||||
<div class="cart__top">
|
<div class="cart__main">
|
||||||
<h1 class="cart__top-title">{{ t('cart.title') }}</h1>
|
<h1 class="cart__main-title">{{ t('cart.title') }}</h1>
|
||||||
<div class="cart__top-inner">
|
|
||||||
<client-only>
|
|
||||||
<p>({{ t('cart.items', productsInCartQuantity, { count: productsInCartQuantity }) }})</p>
|
|
||||||
</client-only>
|
|
||||||
<p>{{ totalPrice }}$</p>
|
|
||||||
<ui-button
|
|
||||||
:type="'button'"
|
|
||||||
class="cart__top-button"
|
|
||||||
@click="buyOrder"
|
|
||||||
>
|
|
||||||
<icon name="material-symbols:add" size="20" />
|
|
||||||
{{ t('buttons.checkout') }}
|
|
||||||
</ui-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<client-only>
|
<client-only>
|
||||||
<div class="cart__list">
|
<div class="cart__list">
|
||||||
<div class="cart__list-inner" v-if="productsInCart.length">
|
<div class="cart__list-inner" v-if="productsInCart.length">
|
||||||
|
|
@ -32,6 +17,47 @@
|
||||||
</div>
|
</div>
|
||||||
</client-only>
|
</client-only>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="cart__checkout">
|
||||||
|
<h2>{{ t('cart.checkout') }}</h2>
|
||||||
|
<client-only>
|
||||||
|
<p>{{ t('cart.items', productsInCartQuantity, { count: productsInCartQuantity }) }}</p>
|
||||||
|
</client-only>
|
||||||
|
<h6>{{ t('cart.totalPrice') }}: <span>{{ totalPrice }}$</span></h6>
|
||||||
|
<div class="cart__checkout-promo">
|
||||||
|
<button class="current" ref="button" @click="setMenuVisible(!isMenuVisible)">
|
||||||
|
<span v-if="selectedPromo">{{ selectedPromo.node.code }}</span>
|
||||||
|
<span v-else>{{ t('cart.promocode.apply') }}</span>
|
||||||
|
</button>
|
||||||
|
<transition name="fromTop">
|
||||||
|
<div class="menu" ref="menu" v-if="isMenuVisible">
|
||||||
|
<div class="menu__list" v-if="promocodes.length">
|
||||||
|
<div
|
||||||
|
class="menu__list-item"
|
||||||
|
v-for="promo of promocodes"
|
||||||
|
:key="promo.node.uuid"
|
||||||
|
@click="selectPromo(promo)"
|
||||||
|
>
|
||||||
|
<span class="code">{{ promo.node.code }}</span>
|
||||||
|
<span class="value">
|
||||||
|
<span v-if="promo.node.discountType === 'amount'">{{ promo.node.discount + '$' }}</span>
|
||||||
|
<span v-else>{{ promo.node.discount + '%' }}</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="empty" v-else>{{ t('cart.promocode.empty') }}</p>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
</div>
|
||||||
|
<ui-button
|
||||||
|
:type="'button'"
|
||||||
|
class="cart__checkout-button"
|
||||||
|
@click="buyOrder(selectedPromo.node.uuid)"
|
||||||
|
>
|
||||||
|
<icon name="material-symbols:shopping-cart-checkout" size="20" />
|
||||||
|
{{ t('buttons.checkout') }}
|
||||||
|
</ui-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -44,10 +70,13 @@ import {useExactProducts} from "@composables/products/useExactProducts";
|
||||||
const {t} = useI18n();
|
const {t} = useI18n();
|
||||||
const cartStore = useCartStore();
|
const cartStore = useCartStore();
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
|
const promocodeStore = usePromocodeStore();
|
||||||
const { $appHelpers } = useNuxtApp();
|
const { $appHelpers } = useNuxtApp();
|
||||||
|
|
||||||
const isAuthenticated = computed(() => userStore.isAuthenticated);
|
const isAuthenticated = computed(() => userStore.isAuthenticated);
|
||||||
|
|
||||||
|
const promocodes = computed(() => promocodeStore.promocodes);
|
||||||
|
|
||||||
const cookieCart = useCookie($appHelpers.COOKIES_CART_KEY, {
|
const cookieCart = useCookie($appHelpers.COOKIES_CART_KEY, {
|
||||||
default: () => [],
|
default: () => [],
|
||||||
path: '/',
|
path: '/',
|
||||||
|
|
@ -56,6 +85,20 @@ const cookieCart = useCookie($appHelpers.COOKIES_CART_KEY, {
|
||||||
const { buyOrder } = useOrderBuy();
|
const { buyOrder } = useOrderBuy();
|
||||||
const { products, getExactProducts } = useExactProducts();
|
const { products, getExactProducts } = useExactProducts();
|
||||||
|
|
||||||
|
const menu = ref(null);
|
||||||
|
const button = ref(null);
|
||||||
|
const isMenuVisible = ref(false);
|
||||||
|
const setMenuVisible = (state) => {
|
||||||
|
isMenuVisible.value = state;
|
||||||
|
};
|
||||||
|
onClickOutside(menu, () => setMenuVisible(false), { ignore: [button] });
|
||||||
|
|
||||||
|
const selectedPromo = ref(null);
|
||||||
|
const selectPromo = (promo) => {
|
||||||
|
setMenuVisible(false);
|
||||||
|
selectedPromo.value = promo;
|
||||||
|
};
|
||||||
|
|
||||||
const cartUuids = computed<string[]>(() => {
|
const cartUuids = computed<string[]>(() => {
|
||||||
return cookieCart.value.map(item => item.productUuid);
|
return cookieCart.value.map(item => item.productUuid);
|
||||||
});
|
});
|
||||||
|
|
@ -121,20 +164,15 @@ setPageTitle(t('breadcrumbs.cart'));
|
||||||
|
|
||||||
&__wrapper {
|
&__wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
align-items: flex-start;
|
||||||
gap: 50px;
|
gap: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__top {
|
&__main {
|
||||||
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
flex-direction: column;
|
||||||
justify-content: space-between;
|
gap: 50px;
|
||||||
|
|
||||||
&-inner {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 35px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&-title {
|
&-title {
|
||||||
color: $primary_dark;
|
color: $primary_dark;
|
||||||
|
|
@ -143,18 +181,6 @@ setPageTitle(t('breadcrumbs.cart'));
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
letter-spacing: -0.5px;
|
letter-spacing: -0.5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
& p {
|
|
||||||
color: $text;
|
|
||||||
font-size: 18px;
|
|
||||||
font-weight: 400;
|
|
||||||
letter-spacing: -0.5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&-button {
|
|
||||||
width: fit-content;
|
|
||||||
padding-inline: 25px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&__list {
|
&__list {
|
||||||
|
|
@ -165,6 +191,119 @@ setPageTitle(t('breadcrumbs.cart'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__checkout {
|
||||||
|
width: 300px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 15px;
|
||||||
|
border: 1px solid $border;
|
||||||
|
border-radius: $default_border_radius;
|
||||||
|
padding: 20px;
|
||||||
|
|
||||||
|
& h2 {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
color: $primary;
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
& p {
|
||||||
|
color: $text;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 400;
|
||||||
|
letter-spacing: -0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
& h6 {
|
||||||
|
color: $primary;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 500;
|
||||||
|
|
||||||
|
& span {
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-promo {
|
||||||
|
width: 100%;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
& .current {
|
||||||
|
width: 100%;
|
||||||
|
border-radius: $default_border_radius;
|
||||||
|
padding: 8px 12px;
|
||||||
|
font-size: 16px;
|
||||||
|
border: 1px solid $border;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
font-weight: 500;
|
||||||
|
color: $text;
|
||||||
|
}
|
||||||
|
|
||||||
|
& .menu {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 2;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
top: 115%;
|
||||||
|
background-color: $main;
|
||||||
|
padding: 5px 0;
|
||||||
|
border-radius: $default_border_radius;
|
||||||
|
border: 1px solid $border;
|
||||||
|
max-height: 300px;
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
|
&__list {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: start;
|
||||||
|
|
||||||
|
&-item {
|
||||||
|
cursor: pointer;
|
||||||
|
width: 100%;
|
||||||
|
padding: 6px 10px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
color: $text;
|
||||||
|
|
||||||
|
@include hover {
|
||||||
|
background-color: $link_secondary;
|
||||||
|
}
|
||||||
|
|
||||||
|
& .code {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
& .value {
|
||||||
|
font-weight: 700;
|
||||||
|
color: $primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
& .empty {
|
||||||
|
padding: 4px 12px;
|
||||||
|
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: $text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-button {
|
||||||
|
margin-top: 20px;
|
||||||
|
padding-inline: 25px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&__empty {
|
&__empty {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,8 @@
|
||||||
"newPassword": "New password",
|
"newPassword": "New password",
|
||||||
"confirmPassword": "Confirm password",
|
"confirmPassword": "Confirm password",
|
||||||
"confirmNewPassword": "Confirm new password",
|
"confirmNewPassword": "Confirm new password",
|
||||||
"brandsSearch": "Search brands by name..."
|
"brandsSearch": "Search brands by name...",
|
||||||
|
"promocode": "Enter promocode"
|
||||||
},
|
},
|
||||||
"checkboxes": {
|
"checkboxes": {
|
||||||
"remember": "Remember me",
|
"remember": "Remember me",
|
||||||
|
|
@ -332,9 +333,15 @@
|
||||||
"text": "Discover the latest trends, style inspiration, and fashion insights from our editorial team."
|
"text": "Discover the latest trends, style inspiration, and fashion insights from our editorial team."
|
||||||
},
|
},
|
||||||
"cart": {
|
"cart": {
|
||||||
|
"totalPrice": "Total price",
|
||||||
"title": "My Cart",
|
"title": "My Cart",
|
||||||
"items": "no items | {count} item | {count} items",
|
"items": "no items | {count} item | {count} items",
|
||||||
"empty": "Your cart is empty."
|
"empty": "Your cart is empty.",
|
||||||
|
"checkout": "Checkout",
|
||||||
|
"promocode": {
|
||||||
|
"apply": "Apply a promocode",
|
||||||
|
"empty": "You don't have any promocodes"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"wishlist": {
|
"wishlist": {
|
||||||
"title": "My Wishlist",
|
"title": "My Wishlist",
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,8 @@
|
||||||
"newPassword": "Новый пароль",
|
"newPassword": "Новый пароль",
|
||||||
"confirmPassword": "Подтвердите пароль",
|
"confirmPassword": "Подтвердите пароль",
|
||||||
"confirmNewPassword": "Подтвердите новый пароль",
|
"confirmNewPassword": "Подтвердите новый пароль",
|
||||||
"brandsSearch": "Поиск брендов по названию..."
|
"brandsSearch": "Поиск брендов по названию...",
|
||||||
|
"promocode": "Введите промокод"
|
||||||
},
|
},
|
||||||
"checkboxes": {
|
"checkboxes": {
|
||||||
"remember": "Запомнить меня",
|
"remember": "Запомнить меня",
|
||||||
|
|
@ -332,9 +333,15 @@
|
||||||
"text": "Узнавайте о последних трендах, источниках вдохновения для стиля и модных инсайтах от нашей редакции."
|
"text": "Узнавайте о последних трендах, источниках вдохновения для стиля и модных инсайтах от нашей редакции."
|
||||||
},
|
},
|
||||||
"cart": {
|
"cart": {
|
||||||
|
"totalPrice": "Итог",
|
||||||
"title": "Моя корзина",
|
"title": "Моя корзина",
|
||||||
"items": "нет товаров | {count} товар | {count} товара | {count} товаров",
|
"items": "нет товаров | {count} товар | {count} товара | {count} товаров",
|
||||||
"empty": "Ваша корзина пуста"
|
"empty": "Ваша корзина пуста",
|
||||||
|
"checkout": "Оформление",
|
||||||
|
"promocode": {
|
||||||
|
"apply": "Примените промокод",
|
||||||
|
"empty": "У вас нет промокодов"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"wishlist": {
|
"wishlist": {
|
||||||
"title": "Мои Избранные",
|
"title": "Мои Избранные",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue