184 lines
5.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup>
import { computed, onMounted, provide, reactive, ref, watch } from 'vue'
import Header from '@/components/Header.vue'
import CardList from '@/components/CardList.vue'
import Drawer from '@/components/Drawer.vue'
import axios from 'axios'
import Spinner from '@/components/Spinner.vue'
import { toast } from 'vue3-toastify'
import 'vue3-toastify/dist/index.css';
const showDrawer = ref(false);
const items = ref([]);
const isLoading = ref(false);
const filters = reactive({
searchQuery: '',
sortBy: ''
});
const isCreatingOrder = ref(false);
const fetchItems = async (filters = {}) => {
const params = {};
if (filters.searchQuery) {
params.title = '*' + filters.searchQuery + '*'
}
if (filters.sortBy) {
params.sortBy = filters.sortBy
}
try {
isLoading.value = true
const { data } = await axios.get(`${import.meta.env.VITE_API_URL}/items`, { params });
items.value = data
} catch (e) {
console.error('Some error', e)
} finally {
isLoading.value = false
}
}
onMounted(fetchItems)
watch(filters, fetchItems)
const toggleToFavorite = async (item) => {
try {
item.isFavorite = !item.isFavorite;
await axios.patch(`${import.meta.env.VITE_API_URL}/items/${item.id}`, item);
if (item.isFavorite) {
toast("Добавлено в избранное", {
"type": "success",
"hideProgressBar": true,
"transition": "slide",
"dangerouslyHTMLString": true,
"position": "bottom-right",
})
}
} catch (e) {
console.log('Error', e)
toast("Ошибка при добавлении в избранное", {
"type": "error",
"hideProgressBar": true,
"transition": "slide",
"dangerouslyHTMLString": true,
"position": "bottom-right",
})
}
}
const toggleToCart = async (item) => {
try {
item.isAdded = !item.isAdded;
await axios.patch(`${import.meta.env.VITE_API_URL}/items/${item.id}`, item);
if (item.isAdded) {
toast("Добавлено в корзину", {
"type": "success",
"hideProgressBar": true,
"transition": "slide",
"dangerouslyHTMLString": true,
"position": "bottom-right",
})
}
} catch (e) {
console.log('Error', e)
}
}
const createOrder = async () => {
try {
isCreatingOrder.value = true;
const { data } = await axios.post(`${import.meta.env.VITE_API_URL}/orders`, {
items: cart.value,
totalPrice: totalPrice.value
});
items.value.forEach((item) => {
item.isAdded = false;
});
await axios.patch(`${import.meta.env.VITE_API_URL}/items`, items.value);
toast("Заказ успешно оформлен", {
"type": "success",
"hideProgressBar": true,
"transition": "slide",
"dangerouslyHTMLString": true,
"position": "bottom-right",
})
return data;
} catch (e) {
toast("Ошибка при создании заказа", {
"type": "error",
"hideProgressBar": true,
"transition": "slide",
"dangerouslyHTMLString": true,
"position": "bottom-right",
})
} finally {
isCreatingOrder.value = false;
showDrawer.value = false;
}
}
const cart = computed(() => items.value.filter(i => i.isAdded));
const totalPrice = computed(() => cart.value.reduce((res, cur) => {
return res + cur.price
}, 0))
provide('cart', {
cart,
toggleToCart,
totalPrice,
openDrawer: () => showDrawer.value = true,
closeDrawer: () => showDrawer.value = false,
createOrder,
isCreatingOrder,
})
</script>
<template>
<Drawer v-if="showDrawer" :cart="cart" />
<div
class="mt-14 w-4/5 mx-auto bg-white rounded-xl shadow-xl"
>
<Header />
<div class="p-10">
<div class="flex justify-between items-center mb-8">
<h2 class="text-3xl font-bold">Все кроссовки</h2>
<div class="flex gap-4 flex-wrap">
<select class="py-2 px-3 border rounded-md outline-none" v-model="filters.sortBy">
<option value="" disabled>Сортировка по:</option>
<option value="title">По названию</option>
<option value="price">По цене (сначала дешевые)</option>
<option value="-price">По цене (сначала дорогие)</option>
</select>
<div class="relative">
<img class="absolute top-3 left-4" src="/search.svg" alt="Search">
<input v-model="filters.searchQuery" class="border rounded-md py-2 pl-11 pr-4 outline-none focus:border-gray-400" type="text" placeholder="Поиск">
</div>
</div>
</div>
<div v-if="isLoading" class="flex justify-center align-center">
<Spinner/>
</div>
<div v-else>
<CardList
v-if="items.length > 0"
:items="items"
@toggle-to-favorite="toggleToFavorite"
@toggle-to-cart="toggleToCart"
/>
<h2 v-else>Пусто</h2>
</div>
</div>
</div>
</template>