Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Coupons CRUD #18

Merged
merged 5 commits into from
Jul 30, 2024
Merged
Show file tree
Hide file tree
Changes from 4 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
11 changes: 11 additions & 0 deletions src/Contracts/Requests/CreateCoupon.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);

namespace Vanilo\Admin\Contracts\Requests;

use Konekt\Concord\Contracts\BaseRequest;

interface CreateCoupon extends BaseRequest
{
}
11 changes: 11 additions & 0 deletions src/Contracts/Requests/UpdateCoupon.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);

namespace Vanilo\Admin\Contracts\Requests;

use Konekt\Concord\Contracts\BaseRequest;

interface UpdateCoupon extends BaseRequest
{
}
78 changes: 77 additions & 1 deletion src/Http/Controllers/CouponController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,88 @@

namespace Vanilo\Admin\Http\Controllers;

use Vanilo\Admin\Contracts\Requests\CreateCoupon;
use Vanilo\Admin\Contracts\Requests\UpdateCoupon;
use Vanilo\Promotion\Contracts\Coupon;
use Vanilo\Promotion\Contracts\Promotion;
use Vanilo\Promotion\Models\CouponProxy;

class CouponController
{
public function create(Promotion $promotion)
{
dd($promotion);
return view('vanilo::coupon.create', [
'promotion' => $promotion,
'coupon' => app(Coupon::class),
]);
}

public function store(Promotion $promotion, CreateCoupon $request)
{
try {
$coupon = CouponProxy::create(
array_merge(
[
'promotion_id' => $promotion->id,
],
$request->validated(),
)
);

flash()->success(__(':code has been created', ['code' => $coupon->code]));
} catch (\Exception $e) {
flash()->error(__('Error: :msg', ['msg' => $e->getMessage()]));

return redirect()->back()->withInput();
}

return redirect(route('vanilo.admin.promotion.show', $promotion));
}

public function show(Promotion $promotion, Coupon $coupon)
{
return view('vanilo::coupon.show', [
'promotion' => $promotion,
'coupon' => $coupon,
]);
}

public function edit(Promotion $promotion, Coupon $coupon)
{
return view('vanilo::coupon.edit', [
'promotion' => $promotion,
'coupon' => $coupon,
]);
}

public function update(Promotion $promotion, Coupon $coupon, UpdateCoupon $request)
{
try {
$coupon->update($request->validated());

flash()->success(__(':code has been updated', ['code' => $coupon->code]));
} catch (\Exception $e) {
flash()->error(__('Error: :msg', ['msg' => $e->getMessage()]));

return redirect()->back()->withInput();
}

return redirect()->route('vanilo.admin.promotion.show', $promotion);
}

public function destroy(Promotion $promotion, Coupon $coupon)
{
try {
$code = $coupon->code;
$coupon->delete();

flash()->warning(__(':code has been deleted', ['code' => $code]));
} catch (\Exception $e) {
flash()->error(__('Error: :msg', ['msg' => $e->getMessage()]));

return redirect()->back();
}

return redirect()->route('vanilo.admin.promotion.show', $promotion);
}
}
2 changes: 1 addition & 1 deletion src/Http/Controllers/PromotionController.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

use Vanilo\Admin\Contracts\Requests\CreatePromotion;
use Vanilo\Admin\Contracts\Requests\UpdatePromotion;
use Vanilo\Promotion\Models\Promotion;
use Vanilo\Promotion\Contracts\Promotion;
use Vanilo\Promotion\Models\PromotionProxy;

class PromotionController extends BaseController
Expand Down
26 changes: 26 additions & 0 deletions src/Http/Requests/CreateCoupon.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

namespace Vanilo\Admin\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Vanilo\Admin\Contracts\Requests\CreateCoupon as CreateCouponContract;

class CreateCoupon extends FormRequest implements CreateCouponContract
{
public function rules()
{
return [
'code' => 'required|string|unique:coupons|min:1|max:255',
'usage_limit' => 'nullable|integer|min:0',
'per_customer_usage_limit' => 'nullable|integer|min:0',
'expires_at' => 'sometimes|nullable|date',
];
}

public function authorize()
{
return true;
}
}
29 changes: 29 additions & 0 deletions src/Http/Requests/UpdateCoupon.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);

namespace Vanilo\Admin\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
use Vanilo\Admin\Contracts\Requests\UpdateCoupon as UpdateCouponContract;

class UpdateCoupon extends FormRequest implements UpdateCouponContract
{
public function rules()
{
$coupon = $this->route('coupon');

return [
'code' => ['required', 'string', Rule::unique('coupons')->ignore($coupon), 'min:1', 'max:255'],
'usage_limit' => 'nullable|integer|min:0',
'per_customer_usage_limit' => 'nullable|integer|min:0',
'expires_at' => 'sometimes|nullable|date',
];
}

public function authorize()
{
return true;
}
}
4 changes: 4 additions & 0 deletions src/Providers/ModuleServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
use Vanilo\Admin\Http\Requests\AssignChannels;
use Vanilo\Admin\Http\Requests\CreateCarrier;
use Vanilo\Admin\Http\Requests\CreateChannel;
use Vanilo\Admin\Http\Requests\CreateCoupon;
use Vanilo\Admin\Http\Requests\CreateLink;
use Vanilo\Admin\Http\Requests\CreateLinkForm;
use Vanilo\Admin\Http\Requests\CreateMasterProduct;
Expand All @@ -49,6 +50,7 @@
use Vanilo\Admin\Http\Requests\SyncModelTaxons;
use Vanilo\Admin\Http\Requests\UpdateCarrier;
use Vanilo\Admin\Http\Requests\UpdateChannel;
use Vanilo\Admin\Http\Requests\UpdateCoupon;
use Vanilo\Admin\Http\Requests\UpdateMasterProduct;
use Vanilo\Admin\Http\Requests\UpdateMasterProductVariant;
use Vanilo\Admin\Http\Requests\UpdateOrder;
Expand Down Expand Up @@ -116,6 +118,8 @@ class ModuleServiceProvider extends BaseBoxServiceProvider
CreateLink::class,
CreatePromotion::class,
UpdatePromotion::class,
CreateCoupon::class,
UpdateCoupon::class,
];

public function register(): void
Expand Down
16 changes: 16 additions & 0 deletions src/resources/routes/breadcrumbs.php
Original file line number Diff line number Diff line change
Expand Up @@ -276,3 +276,19 @@
$breadcrumbs->parent('vanilo.admin.promotion.show', $promotion);
$breadcrumbs->push(__('Edit'), route('vanilo.admin.promotion.edit', $promotion));
});

Breadcrumbs::for('vanilo.admin.coupon.create', function ($breadcrumbs, $promotion) {
$breadcrumbs->parent('vanilo.admin.promotion.show', $promotion);
$breadcrumbs->push(__('Create Coupon'));
});

Breadcrumbs::for('vanilo.admin.coupon.show', function ($breadcrumbs, $promotion, $coupon) {
$breadcrumbs->parent('vanilo.admin.promotion.index');
$breadcrumbs->push($promotion->name, route('vanilo.admin.promotion.show', $promotion));
$breadcrumbs->push($coupon->code, route('vanilo.admin.coupon.show', [$promotion, $coupon]));
});

Breadcrumbs::for('vanilo.admin.coupon.edit', function ($breadcrumbs, $promotion, $coupon) {
$breadcrumbs->parent('vanilo.admin.promotion.show', $promotion);
$breadcrumbs->push($coupon->code);
fulopattila122 marked this conversation as resolved.
Show resolved Hide resolved
});
139 changes: 139 additions & 0 deletions src/resources/views/coupon/_form.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
<div class="mb-3 row">
<label class="col-form-label col-md-2">{{ __('Code') }}</label>
<div class="col-md-10">
{{ Form::text('code', null, [
'class' => 'form-control form-control-sm' . ($errors->has('code') ? ' is-invalid': ''),
'placeholder' => __('Code')
])
}}
@if ($errors->has('code'))
<div class="invalid-feedback">{{ $errors->first('code') }}</div>
@endif
</div>
</div>

<div x-data="usageLimitField" class="mb-3 row">
<label class="col-form-label col-md-2">{{ __('Usage Limit') }}</label>

<div class="col-md-10">
<div class="input-group">
<span class="input-group-text">
{!! icon('stock') !!}
</span>
{{ Form::number('usage_limit', null, [
'class' => 'form-control' . ($errors->has('usage_limit') ? ' is-invalid' : ''),
'placeholder' => __('Usage Limit'),
'min' => 0,
'x-model.number' => 'usageLimit',
'x-bind:readonly' => 'isUsageIsUnlimited',
'x-bind:class' => 'isUsageIsUnlimited ? "bg-light text-secondary text-opacity-25" : ""'
])
}}
<div class="input-group-text">
<input
x-model="isUsageIsUnlimited"
x-on:change="toggleUsageLimitMode"
class="form-check-input mt-0"
type="checkbox"
value="1"
aria-label="Unlimited"
id="usageUnlimitedCheckbox"
>
<label class="form-check-label ps-1" for="usageUnlimitedCheckbox">{{ __('Unlimited') }}</label>
</div>
</div>
</div>

@if ($errors->has('usage_limit'))
<input hidden class="form-control is-invalid">
<div class="invalid-feedback">{{ $errors->first('usage_limit') }}</div>
@endif
</div>

<div x-data="perCustomerUsageLimitField" class="mb-3 row">
<label class="col-form-label col-md-2">{{ __('Per Customer Usage Limit') }}</label>

<div class="col-md-10">
<div class="input-group">
<span class="input-group-text">
{!! icon('stock') !!}
</span>
{{ Form::number('per_customer_usage_limit', null, [
'class' => 'form-control' . ($errors->has('per_customer_usage_limit') ? ' is-invalid' : ''),
'placeholder' => __('Per Customer Usage Limit'),
'min' => 0,
'x-model.number' => 'perCustomerUsageLimit',
'x-bind:readonly' => 'isPerCustomerUsageIsUnlimited',
'x-bind:class' => 'isPerCustomerUsageIsUnlimited ? "bg-light text-secondary text-opacity-25" : ""'
])
}}
<div class="input-group-text">
<input
x-model="isPerCustomerUsageIsUnlimited"
x-on:change="togglePerCustomerUsageLimitMode"
class="form-check-input mt-0"
type="checkbox"
value="1"
aria-label="Unlimited"
id="perCustomerUsageUnlimitedCheckbox"
>
<label class="form-check-label ps-1" for="perCustomerUsageUnlimitedCheckbox">{{ __('Unlimited') }}</label>
</div>
</div>
</div>

@if ($errors->has('per_customer_usage_limit'))
<input hidden class="form-control is-invalid">
<div class="invalid-feedback">{{ $errors->first('per_customer_usage_limit') }}</div>
@endif
</div>

<div class="mb-3 row">
<label class="col-form-label col-md-2">{{ __('Expires at') }}</label>
<div class="col-md-10">
<input
type="datetime-local"
name="expires_at"
value="{{ old('expires_at', $coupon->expires_at) }}"
class="form-control {{ $errors->has('expires_at') ? 'is-invalid' : '' }}"
/>

@if ($errors->has('expires_at'))
<div class="invalid-feedback">{{ $errors->first('expires_at') }}</div>
@endif
</div>
</div>

@push('scripts')
<script>
document.addEventListener('alpine:init', function () {
Alpine.data('usageLimitField', () => ({
isUsageIsUnlimited: @json(is_null(old('usage_limit', $coupon->usage_limit))),
usageLimit: @json(old('usage_limit', $coupon->usage_limit)),
originalUsageLimitValue: @json(old('usage_limit', $coupon->usage_limit)),

toggleUsageLimitMode() {
if (this.isUsageIsUnlimited === true) {
this.usageLimit = null
} else {
this.usageLimit = this.originalUsageLimitValue ?? 0
}
}
}))

Alpine.data('perCustomerUsageLimitField', () => ({
isPerCustomerUsageIsUnlimited: @json(is_null(old('per_customer_usage_limit', $coupon->per_customer_usage_limit))),
perCustomerUsageLimit: @json(old('per_customer_usage_limit', $coupon->per_customer_usage_limit)),
originalPerCustomerUsageLimitValue: @json(old('per_customer_usage_limit', $coupon->per_customer_usage_limit)),

togglePerCustomerUsageLimitMode() {
if (this.isPerCustomerUsageIsUnlimited === true) {
this.perCustomerUsageLimit = null
} else {
this.perCustomerUsageLimit = this.originalPerCustomerUsageLimitValue ?? 0
}
}
}))
})
</script>
@endpush
26 changes: 26 additions & 0 deletions src/resources/views/coupon/create.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
@extends('appshell::layouts.private')

@section('title')
{{ __('Create Coupon') }}
@stop

@section('content')

{!! Form::model($promotion, ['url' => route('vanilo.admin.coupon.store', $promotion), 'autocomplete' => 'off', 'class' => 'row']) !!}

<div class="col-12 col-lg-8 col-xl-9">
<x-appshell::card accent="success">
<x-slot:title>{{ __('Details') }}</x-slot:title>

@include('vanilo::coupon._form')

<x-slot:footer>
<x-appshell::create-button :text="__('Create Coupon')"/>
<x-appshell::cancel-button/>
</x-slot:footer>
</x-appshell::card>
</div>

{!! Form::close() !!}

@stop
Loading