From eb30d4194119fcef71ee1d4657b077a4b7d079de Mon Sep 17 00:00:00 2001 From: Dillon Ngo Date: Mon, 1 Apr 2024 13:56:25 +0800 Subject: [PATCH] Second voucher (first milestone) for user upon reaching 2 completed bookings --- .../Eloquent/Filters/HasActiveReward.php | 33 +++------- .../Filters/HasActiveRewardForAdmin.php | 26 ++++++++ .../Eloquent/Filters/HasVouchersAll.php | 44 ++++++++++++++ .../General/Eloquent/Filters/RandomName.php | 20 ------- .../CreateMilestoneRewardByTransactionJob.php | 38 ++++++++++++ app/Classes/Jobs/ListDocumentsJob.php | 11 ---- .../ControllersLogic/CreateCustomerLogic.php | 8 +-- .../Processors/AuthenticationProcessor.php | 2 +- .../ControllersLogic/CallbackBillplzLogic.php | 9 ++- .../CheckMilestonesForRewardProcessor.php | 13 +++- .../MilestoneRewardByTransactionProcessor.php | 48 +++++++++++++++ .../Constants/MilestoneCreationOptions.php | 5 +- .../ValueObjects/Constants/Milestones.php | 7 ++- app/Http/Resources/VoucherResource.php | 2 +- .../VouchersNavigationBarComponent.vue | 42 +++++++++++++ .../accounts/forms/LogOutFormComponent.vue | 4 +- .../elements/AvailableVouchersComponent.vue | 9 ++- .../elements/ListVouchersComponent.vue | 9 ++- .../SingleUserRewardItemComponent.vue | 5 +- .../CustomerDashboardSectionComponent.vue | 1 + .../CustomerProfileSectionComponent.vue | 3 +- .../CustomerRewardsAdminSectionComponent.vue | 9 ++- .../CustomerRewardsSectionComponent.vue | 21 +++++-- .../VouchersSummaryAdminComponent.vue | 42 +++++++++++++ .../elements/VouchersSummaryComponent.vue | 26 ++++++++ .../assets/vue/vuex/modules/voucherUpdates.js | 60 +++++++++++++++++++ resources/assets/vue/vuex/store.js | 4 +- resources/views/partials/header.blade.php | 7 ++- routes/api.php | 4 +- 29 files changed, 413 insertions(+), 99 deletions(-) create mode 100644 app/Classes/General/Eloquent/Filters/HasActiveRewardForAdmin.php create mode 100644 app/Classes/General/Eloquent/Filters/HasVouchersAll.php delete mode 100644 app/Classes/General/Eloquent/Filters/RandomName.php create mode 100644 app/Classes/Jobs/CreateMilestoneRewardByTransactionJob.php create mode 100644 app/Classes/Modules/Milestones/Processors/MilestoneRewardByTransactionProcessor.php create mode 100644 resources/assets/vue/components/accounts/elements/VouchersNavigationBarComponent.vue create mode 100644 resources/assets/vue/components/general/elements/VouchersSummaryAdminComponent.vue create mode 100644 resources/assets/vue/components/general/elements/VouchersSummaryComponent.vue create mode 100644 resources/assets/vue/vuex/modules/voucherUpdates.js diff --git a/app/Classes/General/Eloquent/Filters/HasActiveReward.php b/app/Classes/General/Eloquent/Filters/HasActiveReward.php index 5770ca6e..26385b96 100644 --- a/app/Classes/General/Eloquent/Filters/HasActiveReward.php +++ b/app/Classes/General/Eloquent/Filters/HasActiveReward.php @@ -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'); + }); } + } diff --git a/app/Classes/General/Eloquent/Filters/HasActiveRewardForAdmin.php b/app/Classes/General/Eloquent/Filters/HasActiveRewardForAdmin.php new file mode 100644 index 00000000..5d69aa4b --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/HasActiveRewardForAdmin.php @@ -0,0 +1,26 @@ +where('user_id', $value) + ->where(function ($query) { + $query->whereHas('reward', function ($subquery) { + $subquery->where('is_active', true); + }); + // ->orWhereDoesntHave('reward'); + }); + } + +} diff --git a/app/Classes/General/Eloquent/Filters/HasVouchersAll.php b/app/Classes/General/Eloquent/Filters/HasVouchersAll.php new file mode 100644 index 00000000..d2ff7a2e --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/HasVouchersAll.php @@ -0,0 +1,44 @@ +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'); + } + } +} diff --git a/app/Classes/General/Eloquent/Filters/RandomName.php b/app/Classes/General/Eloquent/Filters/RandomName.php deleted file mode 100644 index 54024e96..00000000 --- a/app/Classes/General/Eloquent/Filters/RandomName.php +++ /dev/null @@ -1,20 +0,0 @@ -where('is_active', $value); - } - -} diff --git a/app/Classes/Jobs/CreateMilestoneRewardByTransactionJob.php b/app/Classes/Jobs/CreateMilestoneRewardByTransactionJob.php new file mode 100644 index 00000000..86208cc9 --- /dev/null +++ b/app/Classes/Jobs/CreateMilestoneRewardByTransactionJob.php @@ -0,0 +1,38 @@ +transaction = $transaction; + $this->milestones = $milestones; + } + + public function handle() + { + (App()->make(MilestoneRewardByTransactionProcessor::class))->execute($this->transaction, $this->milestones); + } +} diff --git a/app/Classes/Jobs/ListDocumentsJob.php b/app/Classes/Jobs/ListDocumentsJob.php index 6e93062b..25247c50 100644 --- a/app/Classes/Jobs/ListDocumentsJob.php +++ b/app/Classes/Jobs/ListDocumentsJob.php @@ -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(){ diff --git a/app/Classes/Modules/Accounts/ControllersLogic/CreateCustomerLogic.php b/app/Classes/Modules/Accounts/ControllersLogic/CreateCustomerLogic.php index 0f7bdb61..e56c0727 100644 --- a/app/Classes/Modules/Accounts/ControllersLogic/CreateCustomerLogic.php +++ b/app/Classes/Modules/Accounts/ControllersLogic/CreateCustomerLogic.php @@ -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; } diff --git a/app/Classes/Modules/Accounts/Processors/AuthenticationProcessor.php b/app/Classes/Modules/Accounts/Processors/AuthenticationProcessor.php index 707369e9..7e5fca53 100644 --- a/app/Classes/Modules/Accounts/Processors/AuthenticationProcessor.php +++ b/app/Classes/Modules/Accounts/Processors/AuthenticationProcessor.php @@ -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)]; } diff --git a/app/Classes/Modules/Billplzs/ControllersLogic/CallbackBillplzLogic.php b/app/Classes/Modules/Billplzs/ControllersLogic/CallbackBillplzLogic.php index 186ef3b6..a4b80fc4 100644 --- a/app/Classes/Modules/Billplzs/ControllersLogic/CallbackBillplzLogic.php +++ b/app/Classes/Modules/Billplzs/ControllersLogic/CallbackBillplzLogic.php @@ -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]); } -} \ No newline at end of file +} diff --git a/app/Classes/Modules/Milestones/Processors/CheckMilestonesForRewardProcessor.php b/app/Classes/Modules/Milestones/Processors/CheckMilestonesForRewardProcessor.php index 597fa8bc..1a138dfa 100644 --- a/app/Classes/Modules/Milestones/Processors/CheckMilestonesForRewardProcessor.php +++ b/app/Classes/Modules/Milestones/Processors/CheckMilestonesForRewardProcessor.php @@ -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); diff --git a/app/Classes/Modules/Milestones/Processors/MilestoneRewardByTransactionProcessor.php b/app/Classes/Modules/Milestones/Processors/MilestoneRewardByTransactionProcessor.php new file mode 100644 index 00000000..ea9abf9c --- /dev/null +++ b/app/Classes/Modules/Milestones/Processors/MilestoneRewardByTransactionProcessor.php @@ -0,0 +1,48 @@ +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]); + } + } + } + } +} diff --git a/app/Classes/ValueObjects/Constants/MilestoneCreationOptions.php b/app/Classes/ValueObjects/Constants/MilestoneCreationOptions.php index 4631b25b..6e94e610 100644 --- a/app/Classes/ValueObjects/Constants/MilestoneCreationOptions.php +++ b/app/Classes/ValueObjects/Constants/MilestoneCreationOptions.php @@ -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], diff --git a/app/Classes/ValueObjects/Constants/Milestones.php b/app/Classes/ValueObjects/Constants/Milestones.php index 19961d68..6a85abbe 100644 --- a/app/Classes/ValueObjects/Constants/Milestones.php +++ b/app/Classes/ValueObjects/Constants/Milestones.php @@ -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) diff --git a/app/Http/Resources/VoucherResource.php b/app/Http/Resources/VoucherResource.php index 3f3112bb..031cf39f 100644 --- a/app/Http/Resources/VoucherResource.php +++ b/app/Http/Resources/VoucherResource.php @@ -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{ diff --git a/resources/assets/vue/components/accounts/elements/VouchersNavigationBarComponent.vue b/resources/assets/vue/components/accounts/elements/VouchersNavigationBarComponent.vue new file mode 100644 index 00000000..60947cb9 --- /dev/null +++ b/resources/assets/vue/components/accounts/elements/VouchersNavigationBarComponent.vue @@ -0,0 +1,42 @@ + + + diff --git a/resources/assets/vue/components/accounts/forms/LogOutFormComponent.vue b/resources/assets/vue/components/accounts/forms/LogOutFormComponent.vue index 4956260f..5843111c 100644 --- a/resources/assets/vue/components/accounts/forms/LogOutFormComponent.vue +++ b/resources/assets/vue/components/accounts/forms/LogOutFormComponent.vue @@ -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'); } } } - \ No newline at end of file + diff --git a/resources/assets/vue/components/bookings/elements/AvailableVouchersComponent.vue b/resources/assets/vue/components/bookings/elements/AvailableVouchersComponent.vue index 89a56b0f..9b08e7f3 100644 --- a/resources/assets/vue/components/bookings/elements/AvailableVouchersComponent.vue +++ b/resources/assets/vue/components/bookings/elements/AvailableVouchersComponent.vue @@ -12,11 +12,14 @@ {{ item.voucher.code }}
- + + This voucher has expired. + + Valid till {{ item.voucher.end_date }} - No expiry date + Non-expired
@@ -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){ diff --git a/resources/assets/vue/components/bookings/elements/ListVouchersComponent.vue b/resources/assets/vue/components/bookings/elements/ListVouchersComponent.vue index e55e5151..0de8b692 100644 --- a/resources/assets/vue/components/bookings/elements/ListVouchersComponent.vue +++ b/resources/assets/vue/components/bookings/elements/ListVouchersComponent.vue @@ -26,11 +26,14 @@

RM{{ item.voucher.value/100 }} Discount

{{ item.voucher.value }}% Discount

-
+
+ This voucher has expired. +
+
Valid till {{ item.voucher.end_date }}
- No expiry date + Non-expired
@@ -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){ diff --git a/resources/assets/vue/components/companies/elements/SingleUserRewardItemComponent.vue b/resources/assets/vue/components/companies/elements/SingleUserRewardItemComponent.vue index 9cc2409a..164c98c1 100644 --- a/resources/assets/vue/components/companies/elements/SingleUserRewardItemComponent.vue +++ b/resources/assets/vue/components/companies/elements/SingleUserRewardItemComponent.vue @@ -17,11 +17,14 @@

Voucher claimed

+

+ This voucher has expired. +

Valid till {{ item.voucher.end_date }}

- - + Non-expired

diff --git a/resources/assets/vue/components/companies/sections/CustomerDashboardSectionComponent.vue b/resources/assets/vue/components/companies/sections/CustomerDashboardSectionComponent.vue index 5a0766cb..074354ca 100644 --- a/resources/assets/vue/components/companies/sections/CustomerDashboardSectionComponent.vue +++ b/resources/assets/vue/components/companies/sections/CustomerDashboardSectionComponent.vue @@ -201,6 +201,7 @@
+ diff --git a/resources/assets/vue/components/companies/sections/CustomerProfileSectionComponent.vue b/resources/assets/vue/components/companies/sections/CustomerProfileSectionComponent.vue index bd646426..76c28e1d 100644 --- a/resources/assets/vue/components/companies/sections/CustomerProfileSectionComponent.vue +++ b/resources/assets/vue/components/companies/sections/CustomerProfileSectionComponent.vue @@ -141,6 +141,7 @@
+
@@ -213,4 +214,4 @@ } } } - \ No newline at end of file + diff --git a/resources/assets/vue/components/companies/sections/CustomerRewardsAdminSectionComponent.vue b/resources/assets/vue/components/companies/sections/CustomerRewardsAdminSectionComponent.vue index 9429593a..aba22978 100644 --- a/resources/assets/vue/components/companies/sections/CustomerRewardsAdminSectionComponent.vue +++ b/resources/assets/vue/components/companies/sections/CustomerRewardsAdminSectionComponent.vue @@ -52,7 +52,7 @@
- + @@ -69,10 +69,15 @@
- + + +
diff --git a/resources/assets/vue/components/companies/sections/CustomerRewardsSectionComponent.vue b/resources/assets/vue/components/companies/sections/CustomerRewardsSectionComponent.vue index 83567aaf..d781d66e 100644 --- a/resources/assets/vue/components/companies/sections/CustomerRewardsSectionComponent.vue +++ b/resources/assets/vue/components/companies/sections/CustomerRewardsSectionComponent.vue @@ -19,7 +19,7 @@
-
+
@@ -52,7 +52,7 @@
- + @@ -69,11 +69,16 @@
- + +
@@ -108,5 +113,9 @@ diff --git a/resources/assets/vue/components/general/elements/VouchersSummaryAdminComponent.vue b/resources/assets/vue/components/general/elements/VouchersSummaryAdminComponent.vue new file mode 100644 index 00000000..dc4a2a54 --- /dev/null +++ b/resources/assets/vue/components/general/elements/VouchersSummaryAdminComponent.vue @@ -0,0 +1,42 @@ + + + + diff --git a/resources/assets/vue/components/general/elements/VouchersSummaryComponent.vue b/resources/assets/vue/components/general/elements/VouchersSummaryComponent.vue new file mode 100644 index 00000000..e90748af --- /dev/null +++ b/resources/assets/vue/components/general/elements/VouchersSummaryComponent.vue @@ -0,0 +1,26 @@ + + + + diff --git a/resources/assets/vue/vuex/modules/voucherUpdates.js b/resources/assets/vue/vuex/modules/voucherUpdates.js new file mode 100644 index 00000000..a9fd08a5 --- /dev/null +++ b/resources/assets/vue/vuex/modules/voucherUpdates.js @@ -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'); + }, + } +} diff --git a/resources/assets/vue/vuex/store.js b/resources/assets/vue/vuex/store.js index ff10c673..ab554e8a 100644 --- a/resources/assets/vue/vuex/store.js +++ b/resources/assets/vue/vuex/store.js @@ -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 } }) diff --git a/resources/views/partials/header.blade.php b/resources/views/partials/header.blade.php index b618e334..e04131ac 100644 --- a/resources/views/partials/header.blade.php +++ b/resources/views/partials/header.blade.php @@ -61,9 +61,10 @@ - +
+ + +
diff --git a/routes/api.php b/routes/api.php index 460bd772..9d67e62c 100644 --- a/routes/api.php +++ b/routes/api.php @@ -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';