Second voucher (first milestone) for user upon reaching 2 completed bookings

This commit is contained in:
Dillon Ngo
2024-04-01 13:56:25 +08:00
parent bb1cb6d44e
commit eb30d41941
29 changed files with 413 additions and 99 deletions
@@ -2,7 +2,6 @@
namespace App\Classes\General\Eloquent\Filters;
use App\Classes\ValueObjects\Constants\RoleTypes;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Auth;
@@ -12,33 +11,17 @@ class HasActiveReward implements Filter
/**
* @param Builder $builder
* @param $value
* @return mixed
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
if(in_array(Auth::user()->type, RoleTypes::ADMIN_ROLES)){
// $userId = $value !== 1 ? $value : Auth::user()->id;
$userId = $value;
return $builder->where('user_id', $userId)
->where(function ($query) {
$query->whereHas('reward', function ($subquery) {
$subquery->where('is_active', true);
})
->orWhereDoesntHave('reward');
})
->whereDoesntHave('voucher.redemptions.transaction.booking.company.employees', function ($query) use ($userId) {
$query->where('user_id', $userId);
return $builder->where('user_id', Auth::user()->id) //cief todo: should not use Auth::user()->id
->where(function ($query) {
$query->whereHas('reward', function ($subquery) {
$subquery->where('is_active', true);
});
}
else{
return $builder->where('user_id', Auth::user()->id)
->where(function ($query) {
$query->whereHas('reward', function ($subquery) {
$subquery->where('is_active', true);
})
->orWhereDoesntHave('reward');
})
->whereDoesntHave('voucher.redemptions.transaction.owner');
}
// ->orWhereDoesntHave('reward');
});
}
}
@@ -0,0 +1,26 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class HasActiveRewardForAdmin implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->where('user_id', $value)
->where(function ($query) {
$query->whereHas('reward', function ($subquery) {
$subquery->where('is_active', true);
});
// ->orWhereDoesntHave('reward');
});
}
}
@@ -0,0 +1,44 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use App\Classes\ValueObjects\Constants\RoleTypes;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Auth;
class HasVouchersAll implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value)
{
if(in_array(Auth::user()->type, RoleTypes::ADMIN_ROLES)){
// $userId = $value !== 1 ? $value : Auth::user()->id;
$userId = $value;
return $builder->where('user_id', $userId)
->where(function ($query) {
$query->whereHas('reward', function ($subquery) {
$subquery->where('is_active', true);
})
->orWhereDoesntHave('reward');
})
->whereDoesntHave('voucher.redemptions.transaction.booking.company.employees', function ($query) use ($userId) {
$query->where('user_id', $userId);
});
}
else{
return $builder->where('user_id', Auth::user()->id)
->where(function ($query) {
$query->whereHas('reward', function ($subquery) {
$subquery->where('is_active', true);
})
->orWhereDoesntHave('reward');
})
->whereDoesntHave('voucher.redemptions.transaction.owner');
}
}
}
@@ -1,20 +0,0 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class RandomName implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->where('is_active', $value);
}
}
@@ -0,0 +1,38 @@
<?php
namespace App\Classes\Jobs;
use App\Classes\Modules\Milestones\Processors\MilestoneRewardByTransactionProcessor;
use App\Models\Transaction;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class CreateMilestoneRewardByTransactionJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/** @var Transaction */
private $transaction;
/** @var array */
private $milestones;
/**
* CreateMilestoneRewardByTransactionJob constructor.
* @param Transaction $transaction
* @param array $milestones
*/
public function __construct(Transaction $transaction, array $milestones)
{
$this->transaction = $transaction;
$this->milestones = $milestones;
}
public function handle()
{
(App()->make(MilestoneRewardByTransactionProcessor::class))->execute($this->transaction, $this->milestones);
}
}
-11
View File
@@ -44,17 +44,6 @@ class ListDocumentsJob implements ShouldQueue
}
$result = (App()->make(ListDocumentsJobProcessor::class))->execute($this->listGenericJobObject);
//cief todo: Insert into DB: job id, query result, timestamp
// Store the result in the job_results table
//cief todo: why cannot save data in table like this
// $model = new JobResult();
// $model->job_id = $this->job->getJobId();
// $model->result = json_encode($result);
// $model->save();
// Log::error(json_encode($model->id));
}
public function getJobId(){
@@ -11,7 +11,6 @@ use App\Classes\Modules\Companies\Processors\AssignEmployeeProcessor;
use App\Classes\Modules\Companies\Processors\AssignSegmentProcessor;
use App\Classes\Modules\Companies\Processors\CreateCompanyProcessor;
use App\Classes\Modules\Contacts\Processors\CreateContactProcessor;
use App\Classes\Modules\Milestones\Processors\CheckMilestonesForRewardProcessor;
use App\Classes\Modules\Vouchers\Processors\Voucherify\NewCustomerToVoucherifyProcessor;
use App\Classes\Modules\Vouchers\Processors\CreateVoucherProcessor;
use App\Classes\Modules\Companies\DataTransferObjects\EmploymentObject;
@@ -69,9 +68,6 @@ class CreateCustomerLogic extends AbstractControllerLogic
/** @var CreatesSeasonalSegment */
private $createsSeasonalSegment;
/** @var CheckMilestonesForRewardProcessor */
private $checkMilestonesForRewardProcessor;
/** @var NewCustomerToVoucherifyProcessor */
private $newCustomerToVoucherifyProcessor;
@@ -88,12 +84,11 @@ class CreateCustomerLogic extends AbstractControllerLogic
* @param AuthenticationProcessor $authenticationProcessor
* @param GenerateEmailVerificationAttemptProcessor $generateEmailVerificationAttemptProcessor
* @param CreatesSeasonalSegment $createsSeasonalSegment
* @param CheckMilestonesForRewardProcessor $checkMilestonesForRewardProcessor
* @param NewCustomerToVoucherifyProcessor $newCustomerToVoucherifyProcessor
* @param CreateVoucherProcessor $createVoucherProcessor
*/
public function __construct(CreateUserProcessor $createUserProcessor, CreateCompanyProcessor $createCompanyProcessor, CreateContactProcessor $createContactProcessor, AssignEmployeeProcessor $assignEmployeeProcessor, AssignSegmentProcessor $assignSegmentProcessor, AuthenticationProcessor $authenticationProcessor, GenerateEmailVerificationAttemptProcessor $generateEmailVerificationAttemptProcessor,
CreatesSeasonalSegment $createsSeasonalSegment, CheckMilestonesForRewardProcessor $checkMilestonesForRewardProcessor, NewCustomerToVoucherifyProcessor $newCustomerToVoucherifyProcessor, CreateVoucherProcessor $createVoucherProcessor)
CreatesSeasonalSegment $createsSeasonalSegment, NewCustomerToVoucherifyProcessor $newCustomerToVoucherifyProcessor, CreateVoucherProcessor $createVoucherProcessor)
{
$this->createUserProcessor = $createUserProcessor;
$this->createCompanyProcessor = $createCompanyProcessor;
@@ -103,7 +98,6 @@ class CreateCustomerLogic extends AbstractControllerLogic
$this->authenticationProcessor = $authenticationProcessor;
$this->generateEmailVerificationAttemptProcessor = $generateEmailVerificationAttemptProcessor;
$this->createsSeasonalSegment = $createsSeasonalSegment;
$this->checkMilestonesForRewardProcessor = $checkMilestonesForRewardProcessor;
$this->newCustomerToVoucherifyProcessor = $newCustomerToVoucherifyProcessor;
$this->createVoucherProcessor = $createVoucherProcessor;
}
@@ -82,7 +82,7 @@ class AuthenticationProcessor
}
//cief todo: case study 1
//$this->checkMilestonesForRewardProcessor->execute($user, [Milestones::MILESTONE_1]);
//$this->checkMilestonesForRewardProcessor->execute($user, [Milestones::MILESTONE_DEMO_1]);
return ['access_token' => $this->generatesAuthenticationToken->execute($user), 'redirect_url' => $this->authenticationRedirect->url($user)];
}
@@ -26,6 +26,8 @@ use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use App\Classes\Modules\Wallets\Services\RecalculatesWalletBalance;
use App\Classes\Jobs\CreateMilestoneRewardByTransactionJob;
use App\Classes\ValueObjects\Constants\Milestones;
class CallbackBillplzLogic
{
@@ -55,7 +57,9 @@ class CallbackBillplzLogic
* @param FetchesTransaction $fetchesTransaction
* @param UpdatesTransactionStatus $updatesTransactionStatus
* @param UpdatesWalletBalance $updatesWalletBalance
* @param CreateCashBackTransactionProcessor $createCashBackTransactionProcessor
* @param RecalculatesWalletBalance $recalculatesWalletBalance
* @param CreateMilestoneRewardJob $createMilestoneRewardJob
*/
public function __construct(GetBillplzBill $getBillplzBill, FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, UpdatesWalletBalance $updatesWalletBalance, CreateCashBackTransactionProcessor $createCashBackTransactionProcessor, RecalculatesWalletBalance $recalculatesWalletBalance)
{
@@ -87,7 +91,8 @@ class CallbackBillplzLogic
if(!$billPlz) throw new ResourceNotFoundException('Billplz bill not found.');
$transaction = $this->fetchesTransaction->execute(['payment_reference' => $billplzXSignatureObject->getBillPlzId()]);
CreateMilestoneRewardByTransactionJob::dispatch($transaction, [Milestones::MILESTONE_1]);
if($billPlz->state === 'paid') {
$status = ApprovalStatus::APPROVED;
}
@@ -117,4 +122,4 @@ class CallbackBillplzLogic
return $request->method() === 'POST' ? true : view('pages.payments_redirect', ['marking' => $marking ?? null, 'transaction' => $transaction, 'status' => $status]);
}
}
}
@@ -81,9 +81,12 @@ class CheckMilestonesForRewardProcessor
try{
foreach($milestone_constants as $constant)
{
//update milestone progress
/** @var Milestone $milestone */
$milestone = $this->fetchesMilestone->execute(['name' => $constant]);
//update milestone progres
$milestone = Milestone::where('name', $constant)->first();
if(!$milestone) {
Log::error("{$constant} NOT FOUND!");
continue;
}
$result = null;
if($user->milestoneProgress->count() > 0){
$result = $user->milestoneProgress->where('milestone_id', $milestone->id)->first();
@@ -130,6 +133,10 @@ class CheckMilestonesForRewardProcessor
//Voucherify - Create Voucher
$result = $this->createsVoucherifyVoucher->execute($user, intval($reward->value));
}
else if($reward->type == RewardType::REWARD_CODE){
//Voucherify - Get Voucher
$result = $this->fetchesVoucherifyVoucher->execute($user, $reward->value);
}
else{
//Voucherify - Validates Voucher
$ValidateVoucherifyVoucherObject = new ValidateVoucherifyVoucherObject(0, $reward->value, 0.00, $user);
@@ -0,0 +1,48 @@
<?php
namespace App\Classes\Modules\Milestones\Processors;
use App\Classes\Modules\Milestones\Processors\CheckMilestonesForRewardProcessor;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\Milestones;
use App\Models\Booking;
use App\Models\Transaction;
use Illuminate\Support\Facades\Log;
class MilestoneRewardByTransactionProcessor
{
/** @var CheckMilestonesForRewardProcessor */
private $checkMilestonesForRewardProcessor;
/**
* MilestoneRewardByTransactionProcessor constructor.
* @param CheckMilestonesForRewardProcessor $checkMilestonesForRewardProcessor
*/
public function __construct(CheckMilestonesForRewardProcessor $checkMilestonesForRewardProcessor)
{
$this->checkMilestonesForRewardProcessor = $checkMilestonesForRewardProcessor;
}
/**
* @param Transaction $transaction
* @param array $milestones
* @throws \App\Classes\Exceptions\AccessForbiddenException
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(Transaction $transaction, array $milestones)
{
$company = $transaction->owner instanceof Booking ? $transaction->owner()->first()->company : null;
if($company){
$completedBookingCount = count($company->bookings()->where('status', ApprovalStatus::COMPLETED)->get());
Log::info("Number of completed bookings completed for company ".$company->reference. ": " .$completedBookingCount);
if (in_array(Milestones::MILESTONE_1, $milestones)) {
if($completedBookingCount === 2){
$user = $company->employees()->first();
$this->checkMilestonesForRewardProcessor->execute($user, [Milestones::MILESTONE_1]);
}
}
}
}
}
@@ -6,8 +6,9 @@ class MilestoneCreationOptions
{
const OPTIONS_MILESTONE_NAME= [
['text' => 'MILESTONE 1', 'id' => Milestones::MILESTONE_1],
['text' => 'MILESTONE 2', 'id' => Milestones::MILESTONE_2],
['text' => 'MILESTONE 3', 'id' => Milestones::MILESTONE_3],
// ['text' => 'MILESTONE DEMO 1', 'id' => Milestones::MILESTONE_DEMO_1],
// ['text' => 'MILESTONE 2', 'id' => Milestones::MILESTONE_2],
// ['text' => 'MILESTONE 3', 'id' => Milestones::MILESTONE_3],
// ['text' => 'MILESTONE 4', 'id' => Milestones::MILESTONE_4],
// ['text' => 'MILESTONE 5', 'id' => Milestones::MILESTONE_5],
// ['text' => 'MILESTONE 6', 'id' => Milestones::MILESTONE_6],
@@ -4,9 +4,10 @@ namespace App\Classes\ValueObjects\Constants;
class Milestones
{
public const MILESTONE_1 = 'MILESTONE 1'; //Authentication (Sign in) or CreateCustomerLogic (Sign up)
public const MILESTONE_2 = 'MILESTONE 2'; //Create Identification Document
public const MILESTONE_3 = 'MILESTONE 3'; //Assign Company to Segment Logic -segment.assign when accept 1688
public const MILESTONE_1 = 'MILESTONE 1'; //Has 2 successful bookings
// public const MILESTONE_DEMO_1 = 'MILESTONE_DEMO_1 1'; //Authentication (Sign in) or CreateCustomerLogic (Sign up)
// public const MILESTONE_2 = 'MILESTONE 2'; //Create Identification Document
// public const MILESTONE_3 = 'MILESTONE 3'; //Assign Company to Segment Logic -segment.assign when accept 1688
// public const MILESTONE_4 = 'MILESTONE 4'; //Create Bank Logic (Transfer Now from dashboard)
// public const MILESTONE_5 = 'MILESTONE 5'; //Create Booking Logic
// public const MILESTONE_6 = 'MILESTONE 6'; //Create Address Logic (At transfer page before create booking)
+1 -1
View File
@@ -16,7 +16,7 @@ class VoucherResource extends JsonResource
public function toArray($request)
{
$filteredRedemptions = new ArrayObject([]);
if ($request->has('filters') && str_contains($request->input('filters'), "has_active_reward")) {
if ($request->has('filters') && str_contains($request->input('filters'), "has_vouchers_all")) {
$filteredRedemptions = new ArrayObject([]);
}
else{
@@ -0,0 +1,42 @@
<template>
<div class="row h-100 parentContainer">
<div class="col">
<a :href="route('rewards')" >
<div class="text-white all-caps fs-12">Vouchers</div>
<div v-if="showVoucherUpdateIndicator" class="update-indicator"></div>
</a>
</div>
</div>
</template>
<script>
export default {
computed: {
showVoucherUpdateIndicator() {
return this.$store.getters.showVoucherUpdateIndicator;
}
},
created(){
this.submit(this.route('api.voucher.user.list') + '?filters=' + JSON.stringify( { 'has_vouchers_all': true, order_by:{ column:'id', DESC:true }} ), 'get', 'voucherNavigationSection', false, false);
},
methods: {
successHandler(response){
this.$store.dispatch('updateLatestVoucherTimestamp', response.payload.data.length > 0 ? response.payload.data[0].created_at : null)
.then(() => {
this.$store.dispatch('updateVoucherCount', response.payload.data.length);
});
},
}
}
</script>
<style>
.update-indicator {
width: 10px;
height: 10px;
background-color: red;
border-radius: 50%;
position: absolute;
top: 0px;
right: 5px;
}
</style>
@@ -68,11 +68,13 @@
},
successHandler(){
this.$store.dispatch('userAuthentication', {access_token: '', redirect_url: this.route('login')});
this.$store.dispatch('clearVoucher');
},
errorHandler(){
this.$store.dispatch('userAuthentication', {access_token: '', redirect_url: this.route('login')});
this.$store.dispatch('clearVoucher');
}
}
}
</script>
</script>
@@ -12,11 +12,14 @@
<span>{{ item.voucher.code }}</span>
</div>
<div class="row">
<span v-if="item.voucher.end_date">
<span v-if="item.voucher.end_date && new Date() > new Date(item.voucher.end_date)">
This voucher has expired.
</span>
<span v-else-if="item.voucher.end_date">
Valid till {{ item.voucher.end_date }}
</span>
<span v-else>
No expiry date
Non-expired
</span>
</div>
</div>
@@ -62,7 +65,7 @@
fetchVouchers(){
this.isLoading = true;
if(this.employee){
this.submit(route('api.voucher.user.list') + '?filters=' + JSON.stringify( { 'has_active_reward': this.employee.id} ), 'get', this.section, false, false);
this.submit(route('api.voucher.user.list') + '?filters=' + JSON.stringify( { 'has_vouchers_all': this.employee.id} ), 'get', this.section, false, false);
}
},
successHandler(response){
@@ -26,11 +26,14 @@
<p v-if="item.voucher.type == 'AMOUNT'">RM{{ item.voucher.value/100 }} Discount</p>
<p v-if="item.voucher.type == 'PERCENT'">{{ item.voucher.value }}% Discount</p>
</div>
<div class="col" v-if="item.voucher.end_date">
<div class="col" v-if="item.voucher.end_date && new Date() > new Date(item.voucher.end_date)">
This voucher has expired.
</div>
<div class="col" v-else-if="item.voucher.end_date">
Valid till {{ item.voucher.end_date }}
</div>
<div class="col" v-else>
No expiry date
Non-expired
</div>
</div>
</div>
@@ -76,7 +79,7 @@
fetchVouchers(){
this.isLoading = true;
if(this.employee){
this.submit(route('api.voucher.user.list') + '?filters=' + JSON.stringify( { 'has_active_reward': this.employee.id} ), 'get', this.section, false, false);
this.submit(route('api.voucher.user.list') + '?filters=' + JSON.stringify( { 'has_vouchers_all': this.employee.id} ), 'get', this.section, false, false);
}
},
successHandler(response){
@@ -17,11 +17,14 @@
<p v-if="item.voucher && item.voucher.is_redeemed">
Voucher claimed
</p>
<p v-else-if="item.voucher.end_date && new Date() > new Date(item.voucher.end_date)">
This voucher has expired.
</p>
<p v-else-if="item.voucher && item.voucher.end_date">
Valid till {{ item.voucher.end_date }}
</p>
<p v-else>
-
Non-expired
</p>
</div>
</div>
@@ -201,6 +201,7 @@
</div>
</div>
<div class="col-12 col-lg-3">
<vouchers-summary-component></vouchers-summary-component>
<wallet-component :data="company"></wallet-component>
<verification-warning-component v-if="!isLoading" :data="company"></verification-warning-component>
<new-service-announcement-component :data="company"></new-service-announcement-component>
@@ -141,6 +141,7 @@
<div class="col">
<div class="row">
<div class="col m-b-15">
<vouchers-summary-admin-component v-if="company" :company="company"></vouchers-summary-admin-component>
<wallet-component :data="company" :creditable=true></wallet-component>
</div>
</div>
@@ -213,4 +214,4 @@
}
}
}
</script>
</script>
@@ -52,7 +52,7 @@
<div class="col">
<div class="row">
<div class="col" v-if="this.$store.getters.getUserId">
<list-component section="customerVouchersListSection" :endpoint="route('api.voucher.user.list')" :options="{ 'has_active_reward': id }">
<list-component section="customerVouchersListSection" :endpoint="route('api.voucher.user.list')" :options="{ 'has_vouchers_all': id }">
<template slot="list" slot-scope="{data}">
<single-user-reward-item-component :data="data"></single-user-reward-item-component>
</template>
@@ -69,10 +69,15 @@
<div class="col">
<div class="row">
<div class="col" v-if="this.$store.getters.getUserId">
<list-component section="customerRewardsListSection" :endpoint="route('api.reward.list.details.admin', id)" :options="{'is_active': true, order_by:{ column:'order', DESC:false}}">
<!-- <list-component section="customerRewardsListSection" :endpoint="route('api.reward.list.details.admin', id)" :options="{'is_active': true, order_by:{ column:'order', DESC:false}}">
<template slot="list" slot-scope="{data}">
<single-reward-details-item-component :data="data"></single-reward-details-item-component>
</template>
</list-component> -->
<list-component section="customerRewardsListSection" :endpoint="route('api.voucher.user.list')" :options="{'has_active_reward_for_admin': id}">
<template slot="list" slot-scope="{data}">
<single-user-reward-item-component :data="data"></single-user-reward-item-component>
</template>
</list-component>
</div>
</div>
@@ -19,7 +19,7 @@
</div>
</div>
</div>
<div class="col m-r-5 d-none d-md-inline">
<!-- <div class="col m-r-5 d-none d-md-inline">
<div class="row fs-12 text-center">
<div class="col p-t-20 p-b-20 bg-master-lighter tabButton" tab-name="rewards">
<div class="row">
@@ -29,7 +29,7 @@
</div>
</div>
</div>
</div>
</div> -->
<div class="col m-r-5 d-none d-md-inline">
<div class="row fs-12 text-center">
<div class="col p-t-20 p-b-20 bg-master-lighter tabButton" tab-name="used">
@@ -52,7 +52,7 @@
<div class="col">
<div class="row">
<div class="col" v-if="this.$store.getters.getUserId">
<list-component section="customerVouchersListSection" :endpoint="route('api.voucher.user.list')" :options="{ 'has_active_reward': true }">
<list-component section="customerVouchersListSection" :endpoint="route('api.voucher.user.list')" :options="{ 'has_vouchers_all': true }">
<template slot="list" slot-scope="{data}">
<single-user-reward-item-component :data="data"></single-user-reward-item-component>
</template>
@@ -69,11 +69,16 @@
<div class="col">
<div class="row">
<div class="col" v-if="this.$store.getters.getUserId">
<list-component section="customerRewardsListSection" :endpoint="route('api.reward.list.details')" :options="{'random_name': true, order_by:{ column:'order', DESC:false}}">
<!-- <list-component section="customerRewardsListSection" :endpoint="route('api.reward.list.details')" :options="{'has_active_reward': true, order_by:{ column:'order', DESC:false}}">
<template slot="list" slot-scope="{data}">
<single-reward-details-item-component :data="data"></single-reward-details-item-component>
</template>
</list-component>
</list-component> -->
<!-- <list-component section="customerRewardsListSection" :endpoint="route('api.voucher.user.list')" :options="{'has_active_reward': true}">
<template slot="list" slot-scope="{data}">
<single-user-reward-item-component :data="data"></single-user-reward-item-component>
</template>
</list-component> -->
</div>
</div>
</div>
@@ -108,5 +113,9 @@
</template>
<script>
export default {}
export default {
created(){
this.$store.dispatch('markVouchersAsSeen');
}
}
</script>
@@ -0,0 +1,42 @@
<template>
<div class="row parentContainer" style="margin-bottom: 8px;">
<div class="col">
<div class="bg-complete">
<div class="row align-items-end" style="padding: 8px 25px;">
<div class="col-auto">
<a :href="route('customer.reward', company.reference)" target="_blank">
<i class="fa fa-spinner fa-spin m-b-5 text-white" v-show="$store.getters.isLoading(section)"></i>
<div v-show="!$store.getters.isLoading(section)" class="text-primary-lighter fs-10 text-uppercase">Vouchers: <span class="text-white no-margin bold">{{ vouchersCount }}</span><i class="fa fa-external-link text-white m-l-10"></i></div>
</a>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
company: {
type: Object,
required: true
}
},
data(){
return {
section: 'customerVouchersSummaryAdminSection',
vouchersCount: 0,
}
},
created(){
this.submit(this.route('api.voucher.user.list') + '?filters=' + JSON.stringify( { 'has_vouchers_all': this.company.employee.id, order_by:{ column:'id', DESC:true }} ), 'get', this.section, false, false);
},
methods: {
successHandler(response){
this.vouchersCount = response.payload.data.length;
},
}
}
</script>
@@ -0,0 +1,26 @@
<template>
<div class="row parentContainer" style="margin-bottom: 8px;">
<div class="col">
<div class="bg-complete">
<div class="row align-items-end" style="padding: 8px 25px;">
<div class="col-auto">
<a :href="route('rewards')" >
<div class="text-primary-lighter fs-10 text-uppercase">Vouchers: <span class="text-white no-margin bold">{{ vouchersCount }}</span></div>
</a>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
computed: {
vouchersCount() {
return this.$store.getters.getVouchersCount;
}
},
}
</script>
+60
View File
@@ -0,0 +1,60 @@
const initialState = {
vouchersCount: localStorage.getItem('voucher-count') || 0,
latestVoucherTimestamp: localStorage.getItem('latest-voucher-timestamp') || null,
lastSeenVoucherTimestamp: localStorage.getItem('last-seen-voucher-timestamp') || null,
};
export default {
state: { ...initialState },
getters: {
getVouchersCount: state => {
return state.vouchersCount;
},
showVoucherUpdateIndicator: state => {
if (!state.lastSeenVoucherTimestamp && state.voucherCount > 0) {
return true;
}
if (!state.latestVoucherTimestamp) {
return false;
}
const latestTime = new Date(state.latestVoucherTimestamp).getTime();
const lastSeenTime = new Date(state.lastSeenVoucherTimestamp).getTime();
return latestTime > lastSeenTime;
}
},
mutations: {
SET_VOUCHER_LATEST_TIMESTAMP(state, timestamp) {
state.latestVoucherTimestamp = timestamp;
},
SET_VOUCHER_LAST_SEEN_TIMESTAMP(state, timestamp) {
state.lastSeenVoucherTimestamp = timestamp;
},
SET_VOUCHER_COUNT(state, count) {
state.vouchersCount = count;
},
RESET_VOUCHER_STATE(state) {
Object.assign(state, initialState);
}
},
actions: {
updateLatestVoucherTimestamp(store, timestamp){
localStorage.setItem('latest-voucher-timestamp', timestamp);
store.commit('SET_VOUCHER_LATEST_TIMESTAMP', timestamp);
},
markVouchersAsSeen(store) {
const latestVoucherTimestamp = store.state.latestVoucherTimestamp;
localStorage.setItem('last-seen-voucher-timestamp', latestVoucherTimestamp);
store.commit('SET_VOUCHER_LAST_SEEN_TIMESTAMP', latestVoucherTimestamp);
},
updateVoucherCount(store, count){
localStorage.setItem('voucher-count', count);
store.commit('SET_VOUCHER_COUNT', count);
},
clearVoucher(store, count){
localStorage.removeItem('voucher-count');
localStorage.removeItem('latest-voucher-timestamp');
localStorage.removeItem('last-seen-voucher-timestamp');
store.commit('RESET_VOUCHER_STATE');
},
}
}
+3 -1
View File
@@ -7,6 +7,7 @@ import crudRequest from './modules/crudRequest'
import crudRequestV2 from './modules/crudRequestV2'
import authentication from './modules/authentication'
import loadRequestQueue from './modules/loadRequestQueue'
import voucherUpdates from './modules/voucherUpdates'
Vue.use(Vuex);
@@ -18,6 +19,7 @@ export default new Vuex.Store({
createNotification,
crudRequest,
crudRequestV2,
authentication
authentication,
voucherUpdates
}
})
+4 -3
View File
@@ -61,9 +61,10 @@
<div v-if="$store.getters.isCustomer" class="col-auto p-r-20">
<a href="{{route('banks')}}"><div class="text-white all-caps fs-12">Bank Accounts</div></a>
</div>
<!-- <div v-if="$store.getters.isCustomer" class="col-auto p-r-20">
<a href="{{route('rewards')}}"><div class="text-white all-caps fs-12">Vouchers</div></a>
</div> -->
<div v-if="$store.getters.isCustomer" class="col-auto p-r-20">
<vouchers-navigation-bar-component></vouchers-navigation-bar-component>
<!-- <a href="{{route('rewards')}}"><div class="text-white all-caps fs-12">Vouchers</div></a> -->
</div>
</div>
</div>
</div>
+1 -3
View File
@@ -60,15 +60,13 @@ Route::group(['middleware' => 'api', 'prefix' => 'v1', 'as' => 'api.'], function
require __DIR__ . '/wallet.php';
require __DIR__ . '/voucher.php';
require __DIR__ . '/accounting.php';
require __DIR__ . '/reward.php';
require __DIR__ . '/milestone.php';
// require __DIR__ . '/accounting.php'; //cief todo: To check if this is needed
require __DIR__ . '/job.php';
// require __DIR__ . '/rate.php';