Skip to content

Commit

Permalink
Merge pull request #5 from cjmellor/release/v2.0.0
Browse files Browse the repository at this point in the history
feat: Replace Blade Component with Livewire Component
  • Loading branch information
cjmellor authored Jul 22, 2023
2 parents e930eb0 + 095bf45 commit 06eea3a
Show file tree
Hide file tree
Showing 15 changed files with 296 additions and 159 deletions.
74 changes: 35 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ return [
],

'max_rating' => 5,

'undo_rating' => true,
];
```

Expand All @@ -79,20 +81,18 @@ class Recipe extends Model
}
```

Now you can rate this Model:
**Rate the Model**

```php
$recipe = Recipe::find(1);

$recipe->rate(score: 2);
```

You can view how many ratings a particular Model has:
**View Models' ratings**

```php
$recipe->ratings;

// this will return a Collection
```

You can get an overall percentage of the amount of Users' who have rated a Model:
Expand All @@ -107,6 +107,22 @@ $recipe->ratingPercent(maxLength: 5);

This will equate to 80%. A float is returned. Changing the `maxLength` will recalculate the percentage.

You could then use this percentage for the `score` attribute of the component.

> **Note**
>
> By default, the `maxLength` is determined by a config option. You can override this by passing a value to the method.
**Unrating Models**

By default, you can unrate a Model. If you don't want Users' to unrate Models, set the `undo_rating` config option to true.

To unrate a Model, you can use the `unrate` method:

```php
$recipe->unrate();
```

The package comes with a bunch of Attributes that you can use. _The results of these are based off a single Model been rated by two Users' with a `3` and ` 5` rating._

```php
Expand All @@ -118,44 +134,33 @@ $recipe->ratedInTotal; // 2
$recipe->sumRating; // "8"
```

### Blade Component
### Livewire Component

The package comes with an optional blade component for displaying the Models' rating.
To see the ratings in action, you can use the Livewire component. This allows you to show the ratings on the front-end statically and let the User's rate the Model by clicking on the stars.

> **Warning**
>
> You must have both TailwindCSS and FontAwesome installed, though FontAwesome can be replaced with your own preferred icon set**
> You must have both Tailwind CSS and Font Awesome installed, though Font Awesome can be replaced with your own preferred icon set
You must publish the file to get access to it

```shell
php artisan vendor:publish --tag="rating-component"
```

You can now use the new component:
**Use the component**

```html
<x-show-rating score="80.0" />
<livewire:rating size="text-7xl" score="55" :model="$recipe" />
```

The component has customisable attributes:
The component has customisable attributes, including:

```php
public string $color = 'text-yellow-400',
public string $family = 'FontAwesome',
public $innerStars = '\f005 \f005 \f005 \f005 \f005',
public $outerStars = '\f006 \f006 \f006 \f006 \f006',
public float $score = 0.0,
public string $textSize = 'text-2xl',
public string $iconBgColor = 'text-yellow-300';
public string $iconFgColor = 'text-yellow-400';
public string $iconBg = 'far fa-star';
public string $iconFg = 'fas fa-star';
public float $score = 0;
public string $size = 'text-base';
public bool $static = false;
```

> **Info**
>
> The component uses FontAwesome to generate the stars. You can use any icon library that supports using Unicode.
#### **"What about a component that allows you to rate a Model on the front-end?"**

That is out of the scope of this package. I may consider it in the future, or I am happy to receive a PR to add it.
If you have the config for unrating a Model set to `true`, an icon shows that allows you to unrate the Model.

## Testing

Expand All @@ -167,15 +172,6 @@ composer test

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

## Contributing

Please see [CONTRIBUTING](https://github.com/cjmellor/.github/blob/main/CONTRIBUTING.md) for details.

## Credits

- [Chris Mellor](https://github.com/cjmellor)
- [All Contributors](../../contributors)

## License

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.
The MIT Licence (MIT). Please see [Licence File](LICENSE.md) for more information.
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
],
"require": {
"php": "^8.1",
"illuminate/contracts": "^9.0|^10.0"
"illuminate/contracts": "^9.0|^10.0",
"livewire/livewire": "^2.12"
},
"require-dev": {
"laravel/pint": "^1.0",
Expand Down
10 changes: 10 additions & 0 deletions config/rating.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,14 @@
|
*/
'max_rating' => 5,

/*
|--------------------------------------------------------------------------
| Undo Rating
|--------------------------------------------------------------------------
|
| Whether or not a User can undo their rating.
|
*/
'undo_rating' => true,
];
5 changes: 0 additions & 5 deletions pint.json

This file was deleted.

3 changes: 0 additions & 3 deletions resources/views/components/rating.blade.php

This file was deleted.

35 changes: 35 additions & 0 deletions resources/views/livewire/rating.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<div class="inline-flex relative gap-1 group">
@for ($i = 1; $i <= $starRating; $i++)
@php
$width = $this->getStarWidth($i)
@endphp
<div
class="inline-block relative {{ $static ? '' : 'cursor-pointer' }}"
wire:mouseover="{{ $static ? '' : '$set(\'hoverValue\', ' . $i . ')' }}"
wire:mouseout="{{ $static ? '' : '$set(\'hoverValue\', 0)' }}"
wire:click="{{ $static ? '' : 'setRating(' . $i . ')' }}"
>
<!-- Outlined Star -->
<i class="{{ $iconBg }} {{ $iconBgColor }} {{ $size }}"></i>

<!-- Filled Star -->
<div class="absolute top-0 left-0 whitespace-nowrap overflow-hidden w-[{{ $width }}%]">
<i class="{{ $iconFg }} {{ $iconFgColor }} {{ $size }}"></i>
</div>
</div>
@endfor

@if($modelRated)
<div class="ml-6">
<i class="fas fa-circle-check text-green-500 {{ $size }}"></i>
</div>
@endif

@if($this->ratingCanBeChanged())
<div class="ml-6 group-hover:block hidden">
<a class="cursor-pointer" wire:click="undoRating">
<i class="fas fa-circle-xmark {{ $size }} text-red-500 hover:text-red-600"></i>
</a>
</div>
@endif
</div>
38 changes: 14 additions & 24 deletions src/Concerns/CanBeRated.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ trait CanBeRated
/**
* Rate a Model.
*
* @param int $score
* @return \Illuminate\Database\Eloquent\Model|false
*
* @throws \Cjmellor\Rating\Exceptions\CannotBeRatedException
Expand All @@ -34,12 +33,17 @@ public function rate(int $score): Model|bool
return $this->ratings()->save(model: $rating);
}

public function unrate(): bool
{
return $this->ratings()
->where(column: 'user_id', operator: '=', value: auth()->id())
->delete();
}

/**
* A check to see if the User has already rated the Model.
*
* @return bool
*/
protected function alreadyRated(): bool
public function alreadyRated(): bool
{
return $this->ratings()->whereHasMorph(
relation: 'rateable',
Expand All @@ -50,8 +54,6 @@ protected function alreadyRated(): bool

/**
* Get the rating for a Model.
*
* @return \Illuminate\Database\Eloquent\Relations\MorphMany
*/
public function ratings(): MorphMany
{
Expand All @@ -61,24 +63,22 @@ public function ratings(): MorphMany
/**
* Get the all-round percentage of a rated Model.
*
* @param $maxRating
* @return float|int
*
* @throws \Throwable
*/
public function ratingPercent($maxRating): float|int
public function ratingPercent($maxRating = null): float|int
{
throw_if(condition: $maxRating > config(key: 'rating.max_rating', default: 5), exception: MaxRatingException::class);
$maxRating ??= config(key: 'rating.max_rating');

throw_if(condition: $maxRating > config(key: 'rating.max_rating'), exception: MaxRatingException::class);

return ($this->ratedInTotal * $maxRating) > 0
? $this->sumRating / (($this->ratedInTotal * $maxRating) / 100)
return ($this->rated_in_total * $maxRating) > 0
? $this->sum_rating / (($this->rated_in_total * $maxRating) / 100)
: 0;
}

/**
* The amount of times a Model has been rated by Users'.
*
* @return \Illuminate\Database\Eloquent\Casts\Attribute
*/
protected function ratedByUsers(): Attribute
{
Expand All @@ -93,8 +93,6 @@ protected function ratedByUsers(): Attribute

/**
* The amount of times a Model has been rated in total.
*
* @return \Illuminate\Database\Eloquent\Casts\Attribute
*/
protected function ratedInTotal(): Attribute
{
Expand All @@ -105,8 +103,6 @@ protected function ratedInTotal(): Attribute

/**
* Get the average rating for a Model
*
* @return \Illuminate\Database\Eloquent\Casts\Attribute
*/
protected function averageRating(): Attribute
{
Expand All @@ -117,8 +113,6 @@ protected function averageRating(): Attribute

/**
* Get the rating sum for a Model
*
* @return \Illuminate\Database\Eloquent\Casts\Attribute
*/
protected function sumRating(): Attribute
{
Expand All @@ -129,8 +123,6 @@ protected function sumRating(): Attribute

/**
* Get the average rating for a Model rated by Users.
*
* @return \Illuminate\Database\Eloquent\Casts\Attribute
*/
protected function averageRatingByUser(): Attribute
{
Expand All @@ -143,8 +135,6 @@ protected function averageRatingByUser(): Attribute

/**
* Get the rating sum for a Model rated by Users.
*
* @return \Illuminate\Database\Eloquent\Casts\Attribute
*/
protected function averageSumOfUser(): Attribute
{
Expand Down
Loading

0 comments on commit 06eea3a

Please sign in to comment.