Skip to content

Commit

Permalink
implement review
Browse files Browse the repository at this point in the history
  • Loading branch information
Juan Pablo Farias committed Aug 29, 2024
1 parent bd32484 commit b724c0a
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
#### Avaliação NPS
- [ ] Implementar sistema de avaliação de estrelas (1 a 5).
- [ ] Adicionar campo opcional para texto no feedback.
- [ ] Implementar upload de até 5 fotos por avaliação.
<!-- - [ ] Implementar upload de até 5 fotos por avaliação. Não necessário no momento-->
- [ ] Configurar limitação para permitir apenas uma avaliação por local por dia para cada cliente.
- [ ] Implementar verificação de geolocalização para permitir avaliações apenas dentro de 100 metros do local.
- [ ] Configurar tempo limite de 10 minutos para completar a avaliação após iniciá-la.
Expand Down
6 changes: 6 additions & 0 deletions app/Models/Business.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,10 @@ public function user()
{
return $this->belongsTo(User::class);
}

public function reviews()
{
return $this->hasMany(NpsReview::class);
}

}
23 changes: 23 additions & 0 deletions app/Models/NpsReview.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class NpsReview extends Model
{
use HasFactory;

protected $fillable = ['user_id', 'business_id', 'rating', 'feedback'];

public function user()
{
return $this->belongsTo(User::class);
}

public function business()
{
return $this->belongsTo(Business::class);
}
}
5 changes: 5 additions & 0 deletions app/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ public function business()
{
return $this->hasOne(Business::class);
}
public function reviews()
{
return $this->hasMany(NpsReview::class);
}


// Constantes para os tipos de usuário
const TYPE_ADMIN = 'Admin';
Expand Down
110 changes: 110 additions & 0 deletions app/Services/ReviewService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<?php

namespace App\Services;

use App\Models\NpsReview;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;

class ReviewService
{
public function startReview($businessId)
{
$alreadyStarted = NpsReview::where('user_id', Auth::id())
->where('business_id', $businessId)
->whereNull('rating') // Só pega a avaliação se ainda não foi concluída
->first();

if ($alreadyStarted) {
return response()->json(['message' => 'Você já iniciou uma avaliação para este local.'], 403);
}

return NpsReview::create([
'user_id' => Auth::id(),
'business_id' => $businessId,
'started_at' => Carbon::now(),
]);
}

public function storeReview(Request $request, $businessId)
{
$this->validateReviewData($request);

$review = NpsReview::where('user_id', Auth::id())
->where('business_id', $businessId)
->whereNull('rating') // Avaliação ainda não concluída
->first();

if (!$review) {
return response()->json(['message' => 'Avaliação não iniciada ou já concluída.'], 403);
}

if (Carbon::now()->diffInMinutes($review->started_at) > 10) {
return response()->json(['message' => 'Tempo limite para completar a avaliação expirou.'], 403);
}

if ($this->isOutsideAllowedArea($request->input('latitude'), $request->input('longitude'), $review->business)) {
return response()->json(['message' => 'Você está fora da área permitida para avaliação.'], 403);
}

DB::transaction(function () use ($request, $review) {
$review->update([
'rating' => $request->input('rating'),
'feedback' => $request->input('feedback'),
]);
});

return $review;
}

private function validateReviewData(Request $request)
{
$request->validate([
'rating' => 'required|integer|between:1,5',
'feedback' => 'nullable|string'
]);
}

private function isOutsideAllowedArea($userLat, $userLng, $business)
{
$distance = $this->calculateDistance($userLat, $userLng, $business->latitude, $business->longitude);
return $distance > 0.1; // 0.1 km = 100 metros
}

private function calculateDistance($lat1, $lon1, $lat2, $lon2)
{
$earthRadius = 6371; // Raio da Terra em km

$dLat = deg2rad($lat2 - $lat1);
$dLon = deg2rad($lon2 - $lon1);

$a = sin($dLat / 2) * sin($dLat / 2) +
cos(deg2rad($lat1)) * cos(deg2rad($lat2)) *
sin($dLon / 2) * sin($dLon / 2);
$c = 2 * atan2(sqrt($a), sqrt(1 - $a));
return $earthRadius * $c; // Distância em km
}

public function deleteReview($reviewId)
{
$review = NpsReview::findOrFail($reviewId);

DB::transaction(function () use ($review) {
$review->delete();
});

return true;
}

public function getReviewsByBusiness($businessId)
{
return NpsReview::where('business_id', $businessId)->get();
}

public function getReviewById($id)
{
return NpsReview::findOrFail($id);
}
}
31 changes: 31 additions & 0 deletions database/migrations/2024_08_29_002857_create_nps_reviews_table.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration {
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('nps_reviews', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->onDelete('cascade'); // Usuário que fez a avaliação
$table->foreignId('business_id')->constrained()->onDelete('cascade'); // Empresa que foi avaliada
$table->tinyInteger('rating')->unsigned(); // Avaliação de 1 a 5 estrelas
$table->text('feedback')->nullable(); // Texto opcional para feedback
$table->timestamp('started_at')->nullable();
$table->timestamps();
});
}

/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('nps_reviews');
}
};

0 comments on commit b724c0a

Please sign in to comment.