Skip to content

Commit

Permalink
feat: search layout (#12)
Browse files Browse the repository at this point in the history
  • Loading branch information
huynamboz authored Dec 26, 2023
1 parent 54e4b34 commit 9e34032
Show file tree
Hide file tree
Showing 15 changed files with 574 additions and 26 deletions.
81 changes: 81 additions & 0 deletions src/components/commons/atoms/ADropdownStatic.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<template>
<div class="w-full">
<div
class="cursor-pointer hover:bg-slate-100 px-3 py-2 rounded-md flex justify-between items-center text-lg font-bold"
@click="isShow = !isShow"
>
<p>{{ title }}</p>
<i v-show="!isShow" class="ri-arrow-down-s-line font-bold"></i>
<i v-show="isShow" class="ri-arrow-up-s-line font-bold"></i>
</div>
<!-- checkbox options -->
<div v-show="isShow" class="flex flex-col gap-2 mt-1 px-4 max-h-[300px] overflow-y-auto">
<div v-for="(item, index) in data" :key="index" class="flex items-center font-medium text-base">
<input
v-model="listSelected"
:type="type"
:class="
type === 'radio'
? 'w-5 h-5 rounded-full border-[1px] border-third-100'
: 'w-5 h-5 rounded-[2px] border-[1px] border-third-100'
"
:value="item?.id"
@change="onChange"
/>
<p class="ml-3">{{ item?.name }}</p>
</div>
</div>
</div>
</template>
<script setup>
import { onBeforeMount, ref, watch } from 'vue'
onBeforeMount(() => {
listSelected.value = props.currentSelected
isShow.value = props.isOpen
})
const emits = defineEmits(['change'])
const props = defineProps({
title: {
type: String,
required: true,
},
isOpen: {
type: Boolean,
default: true,
},
type: {
type: String,
default: 'checkbox',
},
data: {
type: Array,
default: () => [],
},
modelValue: {
type: Array || String,
default: () => [] || '',
},
currentSelected: {
type: Array,
default: () => [],
},
})
const listSelected = ref()
watch(
() => props.currentSelected,
(value) => {
console.log('value current selected', value)
listSelected.value = props.currentSelected
}
)
const isShow = ref(false)
const onChange = () => {
console.log('value----------<', listSelected.value)
emits('change', listSelected.value)
}
</script>
<style lang="scss" scoped></style>
2 changes: 1 addition & 1 deletion src/components/home/HomePage.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script setup>
import BannerSlide from '@/components/sliders/BannerSlide.vue'
import FlashSaleList from '../products/FlashSaleList.vue';
import FlashSaleList from '@/components/products/FlashSaleList.vue'
</script>
<template>
<div class="w-full">
Expand Down
16 changes: 16 additions & 0 deletions src/components/home/PromotionList.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<template>
<div class="w-full mt-20">
<div></div>
<div class="grid grid-cols-3 gap-2">
<img class="row-span-2 h-[408px] w-full object-cover rounded-lg" src="https://s3.envato.com/files/395654070/DSC03177.jpg" alt="" />
<img
class="rounded-lg h-[200px] w-full object-cover"
src="https://d1csarkz8obe9u.cloudfront.net/posterpreviews/fashion-sale-banner-template-design-389dc7a74f096738d1d425314404a2cd_screen.jpg?ts=1605613724"
alt=""
/>
<img class="rounded-lg h-[200px] w-full object-cover" src="https://d1csarkz8obe9u.cloudfront.net/posterpreviews/fashion-sale-banner-template-design-9db9afa9dc48742dd1f63f4b3e970eb1_screen.jpg?ts=1605628683" alt="" />
<img class="rounded-lg h-[200px] w-full object-cover" src="https://picsum.photos/536/354" alt="" />
<img class="rounded-lg h-[200px] w-full object-cover" src="https://picsum.photos/536/354" alt="" />
</div>
</div>
</template>
61 changes: 61 additions & 0 deletions src/components/home/ShopList.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<template>
<div class="w-full mt-20">
<div class="w-full flex justify-between">
<h4 class="text-2xl font-bold">Offical Store</h4>
<h4 class="text-third-100">See All</h4>
</div>
<div class="w-full flex gap-5 mt-5 flex-wrap">
<RouterLink
v-for="(item, index) in shops"
:key="index"
class="h-[220px] shadow-d-30 block bg-white rounded-md w-[183px]"
to="/"
>
<div class="w-full h-[140px] flex justify-center items-center bg-primary-400">
<img class="w-[70%] object-contain" :src="item.logo" alt="">
</div>
<div class="flex py-3 flex-col items-center">
<p class="font-medium">{{ item.name }}</p>
<p class="font-base text-gray-400">Official store</p>
</div>
</RouterLink>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
// create list shop have logo, name, link
const shops = ref([
{
logo: 'https://i0.wp.com/www.swafol.fr/wp-content/uploads/2017/09/Aukey_Logo.png?resize=825%2C363&ssl=1',
name: 'Aukey Official Store',
link: 'https://shopee.vn/mall',
},
{
logo: 'https://upload.wikimedia.org/wikipedia/commons/thumb/b/b4/Samsung_wordmark.svg/7051px-Samsung_wordmark.svg.png',
name: 'Samsung Official',
link: 'https://shopee.vn/mall',
},
{
logo: 'https://upload.wikimedia.org/wikipedia/commons/thumb/5/52/Philips_logo_new.svg/2560px-Philips_logo_new.svg.png',
name: 'Philips',
link: 'https://shopee.vn/mall',
},
{
logo: 'https://asset-3s.3second.co.id/p/logo.png',
name: '#3Second Global',
link: 'https://shopee.vn/mall',
},
{
logo: 'https://inansaigon.vn/ckfinder/userfiles/images/logo-xiaomi-3.png',
name: 'Xiaomi global ',
link: 'https://shopee.vn/mall',
},
{
logo: 'https://1000logos.net/wp-content/uploads/2016/09/Acer-Logo.png',
name: 'Acer',
link: 'https://shope',
},
])
</script>
50 changes: 50 additions & 0 deletions src/components/layouts/BottomFooter.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<template>
<div class="h-fit min-h-[300px] flex flex-col items-center w-full bg-[#f9f9f9] mt-40 px-5">
<div class="w-full max-w-[1440px] mt-10">
<div class="w-full flex justify-between">
<div>
<p class="font-bold text-lg">
Emmable
<span class="text-base font-normal ml-5">
We are a team of passionate people whose goal is to improve everyone's life through disruptive products.
</span>
</p>
<p>© 2021 Emmable</p>
</div>
<div>
<!-- logo -->
<img
class="w-[250px] h-[50px] object-contain"
src="https://openwebdocs.org/img/openwebdocs-logo-light.png"
alt=""
/>
</div>
</div>
</div>
<div class="w-full border-b-[1px] py-5"></div>
<div class="w-full max-w-[1440px] mt-5">
<div class="w-full flex justify-between">
<div class="flex gap-5">
<div class="flex flex-col gap-2">
<p class="font-bold">About</p>
<p>Our Story</p>
<p>Our Team</p>
<p>Careers</p>
<p>Blog</p>
</div>
<div class="flex flex-col gap-2">
<p class="font-bold">Support</p>
<p>Help Center</p>
<p>Terms of Service</p>
<p>Legal</p>
<p>Privacy Policy</p>
</div>
<div class="flex flex-col gap-2">
<p class="font-bold">Contact</p>
<p></p>
</div>
</div>
</div>
</div>
</div>
</template>
28 changes: 25 additions & 3 deletions src/components/layouts/SearchModal/SearchWrapper.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,30 @@
<template>
<div class="w-[500px] h-[35px] border-[1px] flex rounded-md">
<input type="text" placeholder="Enter product..." style="outline: none" class="h-full w-full border-0 bg-transparent rounded-md" />
<div class="h-full w-[35px] bg-[#5a4098] flex justify-center items-center rounded-tr rounded-br">
<div class="w-[900px] h-[35px] border-[1px] flex rounded-md">
<input
v-model="keyword"
type="text"
placeholder="Enter product..."
style="outline: none; border: none !important"
class="h-full w-full border-0 bg-transparent rounded-md"
@keyup.enter="onSearch"
/>
<div
class="h-full w-[50px] bg-[#5a4098] cursor-pointer flex justify-center items-center rounded-tr rounded-br"
@click="onSearch"
>
<i class="ri-search-line text-white"></i>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'
const router = useRouter()
const route = useRoute()
const keyword = ref(route.query.keyword || '')
const onSearch = () => {
const newQuery = { ...route.query, keyword: keyword.value }
router.push({ name: 'search', query: newQuery })
console.log('search', newQuery)
}
</script>
1 change: 0 additions & 1 deletion src/components/products/FlashSaleList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,6 @@ const products = ref([
:slides-per-view="'auto'"
:space-between="10"
@swiper="onSwiper"
@slideChange="onSlideChange"
>
<swiper-slide v-for="product in products" :key="product.name" style="width: auto" class="w-fit">
<ProductCard :product="product" />
Expand Down
88 changes: 88 additions & 0 deletions src/components/search/FilterBox.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<template>
<div class="w-full flex flex-col">
<div class="flex justify-between text-lg items-center">
<p class="font-bold">Filter</p>
<p class="text-third-100" @click="onReset">Reset all</p>
</div>
<div class="mt-5 flex flex-col gap-5">
<div></div>
<ADropdownStatic
:data="listCategory"
title="By category"
:current-selected="currentCategory"
@change="onSelectCategory"
/>
<ADropdownStatic
:data="condition"
type="radio"
title="Condition"
:current-selected="currentCondition"
@change="onSelectCondition"
/>
</div>
</div>
</template>
<script setup>
import ADropdownStatic from '@/components/commons/atoms/ADropdownStatic.vue'
import { computed, ref, watch, onBeforeMount } from 'vue'
import { useMasterStore } from '@/stores/master.store'
import { useRouter, useRoute } from 'vue-router'
const route = useRoute()
const router = useRouter()
const routeQuery = computed(() => route.query)
const masterStore = useMasterStore()
const currentCategory = ref([])
const currentCondition = ref(null)
watch(
() => routeQuery.value,
() => {
try {
handleRoute()
} catch (error) {
console.log('error', error)
}
}
)
const handleRoute = () => {
const { category, condition } = routeQuery.value
currentCategory.value = category && Array.isArray(category) ? category : category ? [category] : []
currentCondition.value = condition
}
onBeforeMount(() => {
handleRoute()
})
defineEmits(['update:modelValue'])
const listCategory = computed(() => masterStore.state.categories)
const condition = ref([
{
id: 1,
name: 'New',
},
{
id: 2,
name: 'Used',
},
{
id: 3,
name: 'Like new',
},
])
const onSelectCategory = (value) => {
const newQuery = { ...route.query, category: value }
router.push({ name: 'search', query: newQuery })
}
const onReset = () => {
const keyword = route.query.keyword
router.push({ name: 'search', query: { keyword } })
}
const onSelectCondition = (value) => {
const newQuery = { ...route.query, condition: value }
router.push({ name: 'search', query: newQuery })
}
</script>
Loading

0 comments on commit 9e34032

Please sign in to comment.