Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions config/rapidez/frontend.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@
'history' => [],
'search-suggestions' => [],
'categories' => [],
'popular-products' => ['size' => 4],

// For example:
// 'blogs' => [
// 'size' => 3, // Optional; Overrides the default `size` as defined below
// ],
'products' => [
'size' => 4, // Optional; Overrides the default `size` as defined below
],
],

'size' => 3,
'size' => 4,
],

// The structure is `'store_code' => 'folder_path'`
Expand Down
4 changes: 2 additions & 2 deletions resources/js/components/Elements/Toggler.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ export default {
this.isOpen = this.open
},
methods: {
toggle() {
this.isOpen = !this.isOpen
toggle(shouldOpen) {
this.isOpen = shouldOpen ?? !this.isOpen

if (this.callback) {
this.callback(this.isOpen)
Expand Down
2 changes: 1 addition & 1 deletion resources/views/components/autocomplete/input.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
id="autocomplete-form"
method="get"
action="{{ route('search') }}"
class="flex relative z-header-autocomplete"
class="flex relative"
{{-- Turbo does not understand redirects to external URLs yet --}}
data-turbo="false"
>
Expand Down
2 changes: 1 addition & 1 deletion resources/views/components/autocomplete/title.blade.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{{-- This title is shown in the search autocomplete above the products and categories --}}
<div {{ $attributes->twMerge('text-muted text-xs font-semibold pb-2 px-5') }}>
<div {{ $attributes->twMerge('text-muted text-xs pb-1 px-5') }}>
{{ $slot }}
</div>
1 change: 1 addition & 0 deletions resources/views/layouts/partials/header.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@
</div>
</nav>
</div>

</header>
113 changes: 75 additions & 38 deletions resources/views/layouts/partials/header/autocomplete.blade.php
Original file line number Diff line number Diff line change
@@ -1,42 +1,79 @@
<autocomplete v-slot="autocompleteSlotProps" :hits-per-page="{{ config('rapidez.frontend.autocomplete.size', 3) }}">
<div class="relative w-full">
<ais-instant-search
v-if="autocompleteSlotProps.searchClient"
:search-client="autocompleteSlotProps.searchClient"
:middlewares="autocompleteSlotProps.middlewares"
:index-name="config.index.product"
class="contents"
v-cloak
>
<div class="contents">
<div class="searchbox group/autocomplete">
<ais-autocomplete>
<template v-slot="{ currentRefinement, refine }">
<x-rapidez::autocomplete.input
v-bind:value="currentRefinement"
v-on:focus="() => {
refine($root.autocompleteFacadeQuery || currentRefinement);
$root.autocompleteFacadeQuery = null;
}"
v-on:input="refine($event.currentTarget.value)"
list="search-history"
/>
<div v-on:click="refine('')" class="fixed inset-0 bg-backdrop z-header-autocomplete-overlay hidden group-has-[input:not(:placeholder-shown)]/autocomplete:block group-has-[:focus]/autocomplete:block"></div>
</template>
</ais-autocomplete>
<div class="absolute inset-x-0 top-full mt-1 bg-white rounded-md z-header-autocomplete hidden group-has-[input:not(:placeholder-shown)]/autocomplete:block group-has-[:focus]/autocomplete:block hover:block">
@include('rapidez::layouts.partials.header.autocomplete.results')
<autocomplete v-slot="autocompleteSlotProps" :hits-per-page="{{ config('rapidez.frontend.autocomplete.additionals.products.size', config('rapidez.frontend.autocomplete.size', 3)) }}">
<toggler v-slot="autoCompleteToggler">
<div class="w-full">
<template v-if="autocompleteSlotProps.searchClient">
<ais-instant-search
:search-client="autocompleteSlotProps.searchClient"
:middlewares="autocompleteSlotProps.middlewares"
:index-name="config.index.product"
class="contents"
v-cloak
>
<div>
<ais-autocomplete v-slot="{ currentRefinement, refine }">
<div>
<x-rapidez::autocomplete.input
v-bind:value="currentRefinement"
v-on:focus="() => {
refine($root.autocompleteFacadeQuery || currentRefinement);
$root.autocomeleteFacadeQuery = null;
autoCompleteToggler.toggle(true);
}"
v-on:input="refine($event.currentTarget.value)"
list="search-history"
id="autocomplete-input"
/>
</div>
</ais-autocomplete>
<div class="fixed inset-0 searchbox bg-white group z-header-autocomplete-popup flex flex-col h-full" v-if="autoCompleteToggler.isOpen">
<div class="py-3 bg">
<div class="container">
<input checked type="checkbox" class="prevent-scroll hidden">
<ais-autocomplete v-slot="{ currentRefinement, refine }">
<div class="flex gap-x-3 justify-between">
<img src="https://raw.githubusercontent.com/rapidez/art/master/r.svg" alt="Rapidez logo" height="50" width="50" class="w-14 h-12 object-contain">

<div class="max-w-2xl w-full">
<x-rapidez::autocomplete.input
v-bind:value="currentRefinement"
v-on:focus="() => {
refine($root.autocompleteFacadeQuery || currentRefinement);
$root.autocomeleteFacadeQuery = null;
}"
v-on:input="refine($event.currentTarget.value)"
list="search-history"
/>
</div>

<x-rapidez::button.outline v-on:click="autoCompleteToggler.close(); refine('')" class="bg-white h-12 w-14 px-0 shrink-0">
<x-heroicon-o-x-mark class="size-5" />
</x-rapidez::button.outline>
</div>
</ais-autocomplete>
</div>
</div>

<div class="h-full bg-white overflow-hidden relative z-10">
<div class="size-full overflow-y-auto">
<div class="container pt-5 pb-8 overflow-y-auto">
@include('rapidez::layouts.partials.header.autocomplete.results')
</div>
</div>
</div>
</div>

<ais-stats-analytics></ais-stats-analytics>
</div>
<ais-stats-analytics></ais-stats-analytics>
</div>
</ais-instant-search>
</template>

<div class="relative w-full" v-else>
<x-rapidez::autocomplete.input
v-model="$root.autocompleteFacadeQuery"
v-on:focus="autoCompleteToggler.toggle(true), window.document.dispatchEvent(new window.Event('loadAutoComplete'))"
id="autocomplete-input"
/>
</div>
</ais-instant-search>
<div v-else class="relative w-full">
<x-rapidez::autocomplete.input
v-model="$root.autocompleteFacadeQuery"
v-on:focus="window.document.dispatchEvent(new window.Event('loadAutoComplete'))"
v-on:mouseover="window.document.dispatchEvent(new window.Event('loadAutoComplete'))"
/>
</div>
</div>
</toggler>
</autocomplete>
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
<ais-hits>
<template v-slot="{ items }">
<div v-if="items && items.length" class="font-sans px-5 py-2.5">
<x-rapidez::button.primary
<div v-if="items && items.length">
<x-rapidez::button.outline
type="submit"
form="autocomplete-form"
class="relative group flex items-center gap-x-4 w-full text-sm"
>
<span>@lang('View all products')</span>
</x-rapidez::button.primary>
</x-rapidez::button.outline>
</div>
</template>
</ais-hits>
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
<ais-index v-bind:index-name="config.index.category" v-bind:index-id="'autocomplete_' + config.index.category">
<ais-index v-bind:index-name="config.index.category" v-bind:index-id="'autocomplete_' + config.index.category" class="max-w-2xl w-full mx-auto">
@if ($size = Arr::get($fields, 'size'))
<ais-configure :hits-per-page.camel="{{ $size }}" />
@endif
<ais-hits v-slot="{ items }">
<div class="border-b py-2.5" v-if="items && items.length">
<div v-if="items && items.length">
<x-rapidez::autocomplete.title>
@lang('Categories')
</x-rapidez::autocomplete.title>
<ul class="flex flex-col font-sans">
<li v-for="(item, count) in items" class="flex flex-1 items-center w-full hover:bg-muted">
<a v-bind:href="item.url" class="relative flex items-center group w-full px-5 py-2 text-sm gap-x-2">
<template v-for="parent in item.parents">
<span>@{{ parent }}</span>
<span>&gt;</span>
</template>
<x-rapidez::highlight attribute="name" class="line-clamp-2"/>
<li v-for="(item, count) in items" class="flex flex-1 items-center w-full hover:bg rounded">
<a v-bind:href="item.url" class="relative flex items-center group w-full px-5 py-2 gap-x-2.5 text-sm">
<x-heroicon-o-magnifying-glass class="size-5 text-muted" />

<span>
<x-rapidez::highlight attribute="name" class="line-clamp-2 inline" />

<span class="text-muted inline" v-if="item.parents && item.parents.length">
@lang('in')
<template v-for="parent in item.parents">
<span class="lowercase"> @{{ parent }}</span>
</template>
</span>
</span>
</a>
</li>
</ul>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<ais-state-results v-slot="{ state: { query: searchQuery } }">
<ais-state-results v-slot="{ state: { query: searchQuery } }" class="max-w-2xl w-full mx-auto">
<div>
<div v-if="autocompleteSlotProps.searchHistory && autocompleteSlotProps.searchHistory?.filter(([query, metadata]) => query.includes(searchQuery.toLowerCase())).length" class="border-b py-2">
<div v-if="autocompleteSlotProps.searchHistory && autocompleteSlotProps.searchHistory?.filter(([query, metadata]) => query.includes(searchQuery.toLowerCase())).length">
<x-rapidez::autocomplete.title>
@lang('Previous Searches')
</x-rapidez::autocomplete.title>
Expand All @@ -9,13 +9,14 @@
v-for="[query, metadata] in autocompleteSlotProps.searchHistory
.filter(([query, metadata]) => query.includes(searchQuery.toLowerCase()))
.slice(0, {{ Arr::get($fields, 'size', config('rapidez.frontend.autocomplete.size', 3)) }})"
class="flex flex-1 items-center w-full hover:bg-muted"
class="flex flex-1 items-center w-full hover:bg rounded"
>
<a
v-bind:href="'{{ route('search', ['q' => 'searchPlaceholder']) }}'.replace('searchPlaceholder', encodeURIComponent(query))"
class="relative flex items-center group w-full px-5 py-2 text-sm gap-x-4"
class="relative flex items-center group w-full px-5 py-2 text-sm gap-x-2.5"
data-turbo="false"
>
<x-heroicon-o-clock class="size-5 text-muted shrink-0" />
@{{ query }}
</a>
</li>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<ais-state-results v-slot="{ status, query }">
<ais-state-results v-slot="{ status, query }" class="max-w-2xl w-full mx-auto">
<div v-if="status === 'stalled'" class="flex items-center mx-auto px-5 py-2.5">
<x-rapidez-loading class="size-5 text-gray-200 animate-spin fill-primary" />
<span class="ml-2">@lang('Searching...')</span>
</div>
<ais-hits>
<template v-slot="{ items }">
<div v-if="items.length === 0 && query !== '' && status === 'idle'" class="p-5">
<div v-if="items.length === 0 && query !== '' && status === 'idle'" class="p-5 rounded border border-muted">
<div class="font-bold text text-lg break-all">
@lang('No results found for :searchterm', [
'searchterm' => '<span class="text-primary">"@{{ query }}"</span>'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@

<ais-hits v-slot="{ items }">
<listing
v-bind:query="() => [{
function_score: {
script_score: {
script: {
source: `(doc['reviews_score'].empty ? 0 : doc['reviews_score'].value) * (1 - 1 / Math.max(1, doc['reviews_count'].empty ? 0 : doc['reviews_count'].value))`,
},
},
},
}]"
v-if="!items.length"
v-slot="popularProducts"
v-cloak
:key="'autocomplete-popular-products'"
>
<div>
<ais-instant-search
v-if="popularProducts.searchClient"
:search-client="popularProducts.searchClient"
:index-name="popularProducts.index"
:middlewares="popularProducts.middlewares"
>
<h2 class="font-medium text-2xl mb-5">
@lang('Popular products')
</h2>
{{-- __NO_QUERY__ is a temporary band-aid for https://github.com/searchkit/searchkit/pull/1407 --}}
<ais-configure :page="0" query="__NO_QUERY__"/>

@if ($size = Arr::get($fields, 'size'))
<ais-configure :hits-per-page.camel="{{ $size }}" />
@endif

<ais-hits v-slot="{ items, sendEvent }">
<div v-if="items && items.length" class="overflow-hidden">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 -mx-5 -mb-px *:border-b">
<template v-for="(item, count) in items">
@include('rapidez::listing.partials.item')
</template>
</div>
</div>
</ais-hits>
</ais-instant-search>
</div>
</listing>
</ais-hits>

Original file line number Diff line number Diff line change
@@ -1,40 +1,28 @@
<ais-hits v-bind:index-name="config.index.product" v-bind:index-id="'autocomplete_' + config.index.product">
<template v-slot="{ items, sendEvent }">
<div v-if="items && items.length" class="py-2.5">
<x-rapidez::autocomplete.title>
@lang('Products')
</x-rapidez::autocomplete.title>
<ul class="gap-2 flex flex-col">
<li
v-for="(item, count) in items"
class="hover:bg-muted"
data-testid="autocomplete-item"
>
<a :href="item.url | url" v-on:click="sendEvent('click', item, 'Hit Clicked')" class="group relative flex flex-wrap p-2">
<img
v-if="item.thumbnail"
:src="'/storage/{{ config('rapidez.store') }}/resizes/200/magento/catalog/product' + item.thumbnail + '.webp' | url"
class="shrink-0 self-center object-contain size-16 mix-blend-multiply"
:alt="item.name"
width="200"
height="200"
/>
<x-rapidez::no-image v-else class="mb-3 h-48 rounded-t" />
<div class="flex flex-1 justify-center flex-col px-2">
<x-rapidez::highlight attribute="name"/>
<div v-if="items && items.length">
<div class="mb-5 flex items-center justify-between">
<p class="font-medium text-2xl inline-block">
<ais-state-results v-slot="{ query }">
<template v-if="query && query !== '__NO_QUERY__'">
@lang('Search for'): @{{ query }}
</template>
<template v-else>
@lang('Search')
</template>
</ais-state-results>
</p>

<div class="flex items-center gap-x-0.5 mt-0.5">
<div v-if="item.special_price" class="text-muted font-sans line-through text-xs">
@{{ item.price | price }}
</div>
<div class="text-sm text font-sans font-bold">
@{{ (item.special_price || item.price) | price }}
</div>
</div>
</div>
</a>
</li>
</ul>
@include('rapidez::layouts.partials.header.autocomplete.all-results')
</div>

<div class="overflow-hidden">
<div class="grid grid-cols-1 md:grid-cols-3 xl:grid-cols-4 -mx-5 -mb-px *:border-b">
<template v-for="(item, count) in items">
@include('rapidez::listing.partials.item')
</template>
</div>
</div>
</div>
</template>
</ais-hits>
</ais-hits>
Loading