0

How do I implement a scope where in the user will claim a reward on a specific level and once they claim their rewards, the reward field will no longer display the reward that they have claimed. So for example:

The user is on level 20, on his reward panel, there are 3 available rewards to be claimed, level 10, 15 and 20. So if the user claimed the level 10 reward, it will no longer display on the panel except for level 15 and 20 rewards.

Here is the code for the blade:

 @foreach(App\LevelRewards::getRewards()->get() as $rewards)
 @if(Auth::user()->level >= $rewards->level_required || Auth::user()->level == $rewards->level_required)
    @if(App\ClaimReward::claimLevel()->get())
            <div class="col-lg-2 col-md-3 col-sm-6 col-xs-6" style="margin: 5px 0px;">
               <div class="hovereffect">
                    <a href="#" class="d-block mb-4 h-100">
                   <input type ="hidden" name="id" value="{{$rewards->id}}"/>
                   <img class="img-responsive" src="{{asset('rewards_img/'.$rewards->picture)}}" alt="">
                    </a>
                <div class="overlay">
                 <h2 style="font-size: 14px;">{{$rewards->details}}</h2>
                 @if($rewards->type == 'physical')
                 <button type="button" class="btn btn-success btn-sm" data-toggle="modal" data-target="#claimPhysical" data-details="{{$rewards->details}}" data-id="{{$rewards->id}}" data-level="{{$rewards->level_required}}" data-physical="{{$rewards->item_name}}">
                CLAIM
                </button>
                @else
                <button type="button" class="btn btn-success btn-sm" data-toggle="modal" data-target="#claimDigital" data-id="{{$rewards->id}}" data-level="{{$rewards->level_required}}" data-physical="{{$rewards->item_name}}">
                CLAIM
                </button>
                @endif
      </div>
    <div style="background: #2d2d2d; padding: 9px;">
         <span class="credits_top">Required Level: <span>{{$rewards->level_required}}</span></span>
         <p>{{$rewards->item_name}}</p> 
    </div> 
</div>                                                                  
   @endif
  @endif
@endforeach

And this is the code for the model ClaimReward model:

public function scopeClaimLevel2($query)
{
    return $query->join('level_rewards','level_rewards.id','=','claim_rewards.reward_id')->select('level_rewards.*');
}

Any links and source of information regarding this question will be highly appreciated. Thank you.

Edit: I tried;

public function scopeClaimLevel($query)
{
    return $query->join('claim_rewards','claim_rewards.reward_id','=','level_rewards.id')->select('level_rewards.*');
}
public function scopeGetRewards($query)
{
    return $query
    ->join('claim_rewards','claim_rewards.reward_id','=','level_rewards.id')
    ->whereDoesntHave('claimLevel', function (Builder $query) {
           $query->where('claim_rewards.status', '=', '0');
     }) 
    ->select('level_rewards.*');
}

But it says Call to undefined method Illuminate\Database\Query\Builder::getRelated()'

John Carlo
  • 54
  • 2
  • 13

2 Answers2

0

add another table that will hold rewards thats user already claimed,

and in the foreach check if this reward id exists in this user claimed rewards,

if not so show it and if yes so skip it.

the table will hold 2 fields:

1) user_id

2) rewards_id

shushu304
  • 1,506
  • 1
  • 7
  • 15
  • I think the claim rewards already consists of the following: id, reward_id, user_id – John Carlo Apr 15 '19 at 08:44
  • if so, so add one more field that will hold the status if it was really claimed or not, by default will be 0/false, and after choosing it will change to 1/true – shushu304 Apr 15 '19 at 11:31
  • Sir, my claim_rewards table also has status that is set to 0. 1 if accepted, 2 if rejected. But if I query it out like whereNotIn, it will not show anything because it doesn't have anything to show nor it doesn't have anything existing in the claim_rewards table. – John Carlo Apr 16 '19 at 01:18
  • structure of the tables can be helpfully to help you, after you edit is more clearly... any way looks like you need to change the order of the query – shushu304 Apr 16 '19 at 06:05
0

regarding the comments above,

and after your edit to what you tried,

looks like the order of the query is wrong... put whereDoesntHave before the select,

and change to implementation of it as wrote in Laravel documentation example.

try this:

public function scopeClaimLevel2($query)
{
    return $query
      ->join('claim_rewards','claim_rewards.reward_id','=','level_rewards.id')
      ->whereDoesntHave('claim_rewards', function (Builder $query) {
             $query->where('status', '=', '0');
       }) 
      ->select('level_rewards.*');    

}

edit:

try to change the join, as wrote here: https://laravel.com/docs/5.4/queries#joins

build the join and in it's function set how to join and where status=0

return $query
      ->join('claim_rewards', function ($join) {
          $join->on('claim_rewards.reward_id', '=', 'level_rewards.id')->where('status', '=', '0');
      })
      ->select('level_rewards.*');
shushu304
  • 1,506
  • 1
  • 7
  • 15
  • I've tried it but it says Argument 2 passed to Illuminate/Database/Eloquent/Builder::whereDoesntHave() must be an instance of Closure or null. – John Carlo Apr 16 '19 at 06:43
  • see the edit code... and are you sure you need to check whereDoesntHave status = 0 ... ? need to be 1, correct? – shushu304 Apr 16 '19 at 06:51
  • I can simply edit it to, whereNotIn, but i just tested out a where('claim_reward.status','=','0') to test if it works. Now, it returns the only data that has a status of 0, so for a thought I added whereDoesntHave('claim_rewards.status','=','0') to return the rewards that isn't yet claimed by the user. – John Carlo Apr 16 '19 at 06:59
  • I've edited my question, please see the edited part above. I've tried your method just now but it returns Call to undefined method Illuminate\Database\Query\Builder::claim_rewards() – John Carlo Apr 16 '19 at 07:04