Skip to content

Commit e53bf60

Browse files
committed
Merge branch 'master' into feature/super-attributes-fix
2 parents f31cea0 + 3d77637 commit e53bf60

File tree

10 files changed

+112
-65
lines changed

10 files changed

+112
-65
lines changed

resources/js/components/Product/QuantitySelect.vue

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,16 @@ export default {
3636
methods: {
3737
increase() {
3838
if (this.increasable) {
39-
this.$emit('input', this.clampValue(this.value + this.step))
39+
this.value = this.clampValue(this.value + this.step)
40+
this.$emit('input', this.value)
4041
this.$emit('change')
4142
}
4243
},
4344
4445
decrease() {
4546
if (this.decreasable) {
46-
this.$emit('input', this.clampValue(this.value - this.step))
47+
this.value = this.clampValue(this.value - this.step)
48+
this.$emit('input', this.value)
4749
this.$emit('change')
4850
}
4951
},

resources/js/components/Search/Autocomplete.vue

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ export default {
3535
type: Number,
3636
default: 3,
3737
},
38+
filterQueryString: {
39+
type: String,
40+
},
3841
},
3942
4043
data() {
@@ -127,6 +130,33 @@ export default {
127130
return client
128131
},
129132
133+
async getInstantSearchClientConfig() {
134+
const config = await InstantSearchMixin.methods.getInstantSearchClientConfig.bind(this).call()
135+
136+
config.getBaseFilters = this.getBaseFilters
137+
138+
return config
139+
},
140+
141+
getBaseFilters() {
142+
let extraFilters = []
143+
extraFilters.push({
144+
query_string: {
145+
query: 'visibility:(3 OR 4) OR (NOT _exists_:visibility)',
146+
},
147+
})
148+
149+
if (this.filterQueryString) {
150+
extraFilters.push({
151+
query_string: {
152+
query: this.filterQueryString,
153+
},
154+
})
155+
}
156+
157+
return extraFilters
158+
},
159+
130160
getMiddlewares() {
131161
let middlewares = InstantSearchMixin.methods.getMiddlewares.bind(this).call()
132162

resources/js/mixins.js

Lines changed: 30 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,38 @@
11
import { mask } from './stores/useMask'
2+
import { computed } from 'vue'
23

34
document.addEventListener('vue:loaded', function (event) {
4-
event.detail.vue.mixin({
5-
methods: {
6-
async asyncForEach(array, callback) {
7-
for (let index = 0; index < array.length; index++) {
8-
await callback(array[index], index, array)
9-
}
10-
},
5+
event.detail.vue.config.globalProperties.asyncForEach = async (array, callback) => {
6+
for (let index = 0; index < array.length; index++) {
7+
await callback(array[index], index, array)
8+
}
9+
}
1110

12-
async magentoCart(method, endpoint, data) {
13-
if (window.app.config.globalProperties.loggedIn.value) {
14-
return await window.magentoAPI(method, 'carts/mine/' + endpoint, data)
15-
} else {
16-
return await window.magentoAPI(method, 'guest-carts/' + mask.value + '/' + endpoint, data)
17-
}
18-
},
19-
},
11+
event.detail.vue.config.globalProperties.magentoCart = async (method, endpoint, data) => {
12+
if (window.app.config.globalProperties.loggedIn.value) {
13+
return await window.magentoAPI(method, 'carts/mine/' + endpoint, data)
14+
} else {
15+
return await window.magentoAPI(method, 'guest-carts/' + mask.value + '/' + endpoint, data)
16+
}
17+
}
2018

21-
computed: {
22-
currencySymbolLocation() {
23-
return new Intl.NumberFormat(config.locale.replace('_', '-'), {
24-
style: 'currency',
25-
currency: config.currency,
26-
}).formatToParts(1)?.[0]?.type === 'currency'
27-
? 'left'
28-
: 'right'
29-
},
19+
event.detail.vue.config.globalProperties.currencySymbolLocation = computed(() => {
20+
return new Intl.NumberFormat(config.locale.replace('_', '-'), {
21+
style: 'currency',
22+
currency: config.currency,
23+
}).formatToParts(1)?.[0]?.type === 'currency'
24+
? 'left'
25+
: 'right'
26+
})
3027

31-
currencySymbol() {
32-
return new Intl.NumberFormat(config.locale.replace('_', '-'), {
33-
style: 'currency',
34-
currency: config.currency,
35-
maximumFractionDigits: 0,
36-
})
37-
.format(0)
38-
.replace(/\d/g, '')
39-
.trim()
40-
},
41-
},
28+
event.detail.vue.config.globalProperties.currencySymbol = computed(() => {
29+
return new Intl.NumberFormat(config.locale.replace('_', '-'), {
30+
style: 'currency',
31+
currency: config.currency,
32+
maximumFractionDigits: 0,
33+
})
34+
.format(0)
35+
.replace(/\d/g, '')
36+
.trim()
4237
})
4338
})

resources/views/checkout/partials/sidebar.blade.php

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,12 @@ class="w-10 h-auto object-contain"
6060
<dt>@lang('Tax')</dt>
6161
<dd>@{{ window.price(cart.value.prices.applied_taxes[0].amount.value) }}</dd>
6262
</div>
63-
<div v-if="cart.value.shipping_addresses.length && cart.value.shipping_addresses[0]?.selected_shipping_method">
63+
<div v-if="cart.value.shipping_addresses.length && cart.value.shipping_addresses?.[0]?.selected_shipping_method">
6464
<dt>
6565
@lang('Shipping')<br>
66-
<small class="text-muted">@{{ cart.value.shipping_addresses[0]?.selected_shipping_method.carrier_title }} - @{{ cart.value.shipping_addresses[0]?.selected_shipping_method.method_title }}</small>
66+
<small class="text-muted">@{{ cart.value.shipping_addresses[0].selected_shipping_method.carrier_title }} - @{{ cart.value.shipping_addresses[0].selected_shipping_method.method_title }}</small>
6767
</dt>
68-
<dd>@{{ window.price(cart.value.shipping_addresses[0]?.selected_shipping_method.amount.value) }}</dd>
68+
<dd>@{{ window.price(cart.value.shipping_addresses[0].selected_shipping_method.amount.value) }}</dd>
6969
</div>
7070
<div v-for="discount in cart.value.prices.discounts" class="border-t pt-3 mt-3">
7171
<dt>@{{ discount.label }}</dt>
@@ -77,17 +77,17 @@ class="w-10 h-auto object-contain"
7777
</div>
7878
</x-rapidez::summary>
7979

80-
<div v-if="cart.value.shipping_addresses[0]" class="flex w-full flex-col gap-x-1 bg px-5 py-4 rounded">
80+
<div v-if="cart.value.shipping_addresses?.[0]" class="flex w-full flex-col gap-x-1 bg px-5 py-4 rounded">
8181
<p class="font-lg mb-2 font-bold">
8282
<template v-if="cart.value.billing_address?.same_as_shipping">@lang('Shipping & billing address')</template>
8383
<template v-else>@lang('Shipping address')</template>
8484
</p>
8585
<ul>
86-
<li v-if="cart.value.shipping_addresses[0]?.company">@{{ cart.value.shipping_addresses[0]?.company }}</li>
87-
<li>@{{ cart.value.shipping_addresses[0]?.prefix }} @{{ cart.value.shipping_addresses[0]?.firstname }} @{{ cart.value.shipping_addresses[0]?.middlename }} @{{ cart.value.shipping_addresses[0]?.lastname }} @{{ cart.value.shipping_addresses[0]?.suffix }}</li>
88-
<li>@{{ cart.value.shipping_addresses[0]?.street[0] }} @{{ cart.value.shipping_addresses[0]?.street[1] }} @{{ cart.value.shipping_addresses[0]?.street[2] }}</li>
89-
<li>@{{ cart.value.shipping_addresses[0]?.postcode }} - @{{ cart.value.shipping_addresses[0]?.city }} - @{{ cart.value.shipping_addresses[0]?.country.label }}</li>
90-
<li v-if="cart.value.shipping_addresses[0]?.telephone">@{{ cart.value.shipping_addresses[0]?.telephone }}</li>
86+
<li v-if="cart.value.shipping_addresses[0].company">@{{ cart.value.shipping_addresses[0].company }}</li>
87+
<li>@{{ cart.value.shipping_addresses[0].prefix }} @{{ cart.value.shipping_addresses[0].firstname }} @{{ cart.value.shipping_addresses[0].middlename }} @{{ cart.value.shipping_addresses[0].lastname }} @{{ cart.value.shipping_addresses[0].suffix }}</li>
88+
<li>@{{ cart.value.shipping_addresses[0].street[0] }} @{{ cart.value.shipping_addresses[0].street[1] }} @{{ cart.value.shipping_addresses[0].street[2] }}</li>
89+
<li>@{{ cart.value.shipping_addresses[0].postcode }} - @{{ cart.value.shipping_addresses[0].city }} - @{{ cart.value.shipping_addresses[0].country.label }}</li>
90+
<li v-if="cart.value.shipping_addresses[0].telephone">@{{ cart.value.shipping_addresses[0].telephone }}</li>
9191
</ul>
9292
</div>
9393
<div v-if="cart.value.billing_address && !cart.value.billing_address?.same_as_shipping" class="mt-4 flex w-full flex-col gap-x-1 border p-3">

resources/views/components/quantity.blade.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
is present on the input and the quantity select component.
55
--}}
66
<quantity-select v-slot="qtySelect" {{ $attributes }}>
7-
<div class="flex items-center justify-center border rounded bg-white h-12 self-start">
7+
<div class="flex items-center justify-center border rounded bg-white h-12">
88
<button
99
v-on:click.prevent="qtySelect.decrease"
1010
v-bind:disabled="!qtySelect.decreasable"

src/Commands/IndexCommand.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Rapidez\Core\Events\IndexBeforeEvent;
88
use Rapidez\Core\Facades\Rapidez;
99
use Rapidez\Core\Models\Traits\Searchable;
10+
use Rapidez\ScoutElasticSearch\Console\Commands\ImportCommand;
1011

1112
class IndexCommand extends Command
1213
{
@@ -49,7 +50,7 @@ public function handle()
4950
config()->set('elasticsearch.indices.settings.' . $searchableAs, $indexSettings);
5051
}
5152

52-
$this->call('scout:import', [
53+
$this->call(ImportCommand::class, [
5354
'searchable' => $model,
5455
]);
5556
}

src/Models/Product.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,10 @@ protected function price(): Attribute
291291
->prices
292292
->firstWhere('customer_group_id', $customerGroupId);
293293

294+
if ($price === null) {
295+
return $this->getCustomAttribute('price')?->value;
296+
}
297+
294298
return $price->price ?: $price->min_price;
295299
});
296300
}
@@ -326,7 +330,11 @@ protected function specialPrice(): Attribute
326330
$specialPrice = $this
327331
->prices
328332
->firstWhere('customer_group_id', $customerGroupId)
329-
->min_price;
333+
?->min_price;
334+
335+
if ($specialPrice === null) {
336+
return null;
337+
}
330338

331339
return $specialPrice < $this->price ? $specialPrice : null;
332340
});

src/Models/Traits/HasCustomAttributes.php

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use Illuminate\Database\Eloquent\Casts\Attribute as AttributeCast;
77
use Illuminate\Database\Eloquent\Relations\HasMany;
88
use Illuminate\Support\Arr;
9+
use InvalidArgumentException;
910
use Rapidez\Core\Models\Attribute;
1011
use Rapidez\Core\Models\AttributeDatetime;
1112
use Rapidez\Core\Models\AttributeDecimal;
@@ -76,27 +77,35 @@ public function scopeAttributeHas(Builder $builder, string $attributeCode, calla
7677
);
7778
}
7879

79-
public function scopeWhereAttribute(Builder $builder, string $attributeCode, $operator = null, $value = null)
80+
public function scopeWhereMethodAttribute(Builder $builder, string $method, string $attributeCode, ...$args)
8081
{
81-
return $builder->attributeHas(
82+
if (! method_exists(\Illuminate\Database\Query\Builder::class, $method)) {
83+
throw new InvalidArgumentException('Method is not a valid method');
84+
}
85+
$isOrMethod = str_starts_with($method, 'or');
86+
87+
if ($isOrMethod) {
88+
$method = lcfirst(substr($method, 2));
89+
}
90+
91+
$q = fn ($builder) => $builder->attributeHas(
8292
$attributeCode,
8393
fn ($query) => $query
84-
->where('value', $operator, $value)
94+
->$method('value', ...$args)
8595
->where($this->getCustomAttributeCode(), $attributeCode)
8696
);
97+
98+
return $isOrMethod ? $builder->orWhere($q) : $q($builder);
99+
}
100+
101+
public function scopeWhereAttribute(Builder $builder, string $attributeCode, $operator = null, $value = null)
102+
{
103+
return $this->whereMethodAttribute('where', $attributeCode, $operator, $value);
87104
}
88105

89-
// TODO: This one is a bit a duplicate of the one above,
90-
// can we re-use some code? What if another method
91-
// is needed like whereBetween, whereNull, etc
92106
public function scopeWhereInAttribute(Builder $builder, string $attributeCode, $values = null, $boolean = 'and', $not = false)
93107
{
94-
return $builder->attributeHas(
95-
$attributeCode,
96-
fn ($query) => $query
97-
->whereIn('value', $values, $boolean, $not)
98-
->where($this->getCustomAttributeCode(), $attributeCode)
99-
);
108+
return $this->whereMethodAttribute('whereIn', $attributeCode, $values, $boolean, $not);
100109
}
101110

102111
public function attributeDatetime(): HasMany
@@ -179,10 +188,6 @@ public function customAttributes(): AttributeCast
179188
if ($values = $this->$relation) {
180189
$data->push(...$values);
181190
}
182-
183-
// TODO: Double check if this is actually useful
184-
// it could improve performance / reduce memory
185-
// $this->unsetRelation($relation);
186191
}
187192

188193
return $data->keyBy($this->getCustomAttributeCode());

tests/playwright/.env.testing

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ SESSION_DRIVER=file
2828
PRODUCT_URL_SIMPLE=/wayfarer-messenger-bag.html
2929
PRODUCT_URL_CONFIGURABLE=/stellar-solar-jacket.html
3030
PRODUCT_URL_GROUPED=/set-of-sprite-yoga-straps.html
31+
PRODUCT_URL_SPECIAL_PRICE=/savvy-shoulder-tote.html
3132

3233
CATEGORY_URL_SIMPLE=/gear/bags.html
3334
CATEGORY_URL_CONFIGURABLE=/women/tops-women.html

tests/playwright/product.spec.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ test('product grouped', BasePage.tags, async ({ page }) => {
1616
await new BasePage(page).screenshot('fullpage-footer')
1717
})
1818

19+
test('product special price', BasePage.tags, async ({ page }) => {
20+
await page.goto(process.env.PRODUCT_URL_SPECIAL_PRICE)
21+
await new BasePage(page).screenshot('fullpage-footer')
22+
})
23+
1924
test('wcag', BasePage.tags, async ({ page }, testInfo) => {
2025
await page.goto(process.env.PRODUCT_URL_SIMPLE)
2126
await new BasePage(page).wcag(testInfo)

0 commit comments

Comments
 (0)