Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions app/Actions/Auction/CreateReportAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

namespace Otoszroto\Actions\Auction;

use Otoszroto\Models\Auction;
use Otoszroto\Models\Report;
use Otoszroto\Models\User;

class CreateReportAction
{
public function execute(User $user, Auction $auction, array $reportData): Report
{
$report = new Report($reportData);
$report->reporter_id = $user->id;
$report->auction_id = $auction->id;
$report->save();

return $report;
}
}
56 changes: 56 additions & 0 deletions app/Http/Controllers/Auction/ReportController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

declare(strict_types=1);

namespace Otoszroto\Http\Controllers\Auction;

use Illuminate\Http\RedirectResponse;
use Inertia\Inertia;
use Inertia\Response;
use Otoszroto\Actions\Auction\CreateReportAction;
use Otoszroto\Helpers\SortHelper;
use Otoszroto\Http\Controllers\Controller;
use Otoszroto\Http\Requests\Auction\CreateReportRequest;
use Otoszroto\Http\Resources\ReportResource;
use Otoszroto\Models\Auction;
use Otoszroto\Models\Report;

class ReportController extends Controller
{
public function create(Auction $auction): Response
{
return Inertia::render("Auction/ReportAuction", ["auction" => $auction]);
}

public function store(CreateReportRequest $request, CreateReportAction $createReportAction, Auction $auction): RedirectResponse
{
$user = $request->user();
$validated = $request->validated();
$createReportAction->execute($user, $auction, $validated);

return redirect()->route("auctions.show", ["auction" => $auction])->with(["message" => "Aukcja została zgłoszona."]);
}

public function index(SortHelper $sorter): Response
{
$reports = Report::query()->with(["reporter", "auction"])->where("resolved_at", "=", null);

$perPage = (int)request()->query("per_page", 10);

$query = $sorter->sort($reports, ["id", "created_at"], []);
$query = $sorter->search($query, "id");

return Inertia::render("Auction/Reports", [
"reports" => ReportResource::collection($query->paginate($perPage)),
]);
}

public function show(Report $report): Response
{
$report->load(["reporter", "auction"]);

return Inertia::render("Auction/ShowReport", [
"report" => new ReportResource($report),
]);
}
}
26 changes: 26 additions & 0 deletions app/Http/Requests/Auction/CreateReportRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

namespace Otoszroto\Http\Requests\Auction;

use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Foundation\Http\FormRequest;

class CreateReportRequest extends FormRequest
{
public function authorize(): bool
{
return auth()->check();
}

/**
* @return array<string, ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
"reason" => ["sometimes", "string", "max:255"],
];
}
}
27 changes: 27 additions & 0 deletions app/Http/Resources/ReportResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace Otoszroto\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

class ReportResource extends JsonResource
{
/**
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
"id" => $this->id,
"reporter" => UserResource::make($this->whenLoaded("reporter")),
"auction" => AuctionResource::make($this->whenLoaded("auction")),
"reason" => $this->reason,
"resolvedAt" => optional($this->resolved_at)?->toDateTimeString(),
"createdAt" => $this->created_at,
"updatedAt" => $this->updated_at,
];
}
}
50 changes: 50 additions & 0 deletions app/Models/Report.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

declare(strict_types=1);

namespace Otoszroto\Models;

use Carbon\Carbon;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

/**
* @property int $id
* @property int $reporter_id
* @property int $auction_id
* @property string $reason
* @property Carbon $resolved_at
* @property Carbon $created_at
* @property Carbon $updated_at
* @property User $reporter
* @property Auction $auction
*/
class Report extends Model
{
use HasFactory;

public $timestamps = true;
protected $fillable = [
"reporter_id",
"auction_id",
"reason",
"resolved_at",
];

/**
* @return BelongsTo<User, $this>
*/
public function reporter(): BelongsTo
{
return $this->belongsTo(User::class, "reporter_id");
}

/**
* @return BelongsTo<Auction, $this>
*/
public function auction(): BelongsTo
{
return $this->belongsTo(Auction::class, "auction_id");
}
}
25 changes: 25 additions & 0 deletions database/factories/ReportFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;
use Otoszroto\Models\Auction;
use Otoszroto\Models\User;

/**
* @extends Factory<Report>
*/
class ReportFactory extends Factory
{
public function definition(): array
{
return [
"reporter_id" => User::factory(),
"auction_id" => Auction::factory(),
"reason" => fake()->text(200),
"resolved_at" => null,
];
}
}
28 changes: 28 additions & 0 deletions database/migrations/0001_01_01_000005_create_reports_table.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Otoszroto\Models\Auction;
use Otoszroto\Models\User;

return new class() extends Migration {
public function up(): void
{
Schema::create("reports", function (Blueprint $table): void {
$table->id();
$table->foreignIdFor(User::class, "reporter_id")->constrained("users")->cascadeOnDelete();
$table->foreignIdFor(Auction::class, "auction_id")->constrained("auctions")->cascadeOnDelete();
$table->text("reason")->nullable();
$table->timestamp("resolved_at")->nullable();
$table->timestamps();
});
}

public function down(): void
{
Schema::dropIfExists("reports");
}
};
1 change: 1 addition & 0 deletions database/seeders/DatabaseSeeder.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public function run(): void
AuctionSeeder::class,
PermissionsSeeder::class,
RolesSeeder::class,
ReportSeeder::class,
]);
}
}
16 changes: 16 additions & 0 deletions database/seeders/ReportSeeder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

declare(strict_types=1);

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use Otoszroto\Models\Report;

class ReportSeeder extends Seeder
{
public function run(): void
{
Report::factory()->count(30)->create();
}
}
25 changes: 25 additions & 0 deletions resources/js/Pages/Auction/ReportAuction.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React from 'react';
import {Form} from "@inertiajs/react";
import { Auction } from "@/Types/auction";

type Props = {
errors: any;
auction: Auction;
}

export function ReportAuction({errors, auction}: Props) {
return (
<>
<h1 className={"text-lg font-semibold"}>Report auction</h1>
<Form
action={`/auctions/${auction.id}/report`}
method="POST"
>
<input type="text" placeholder="Reason" name="reason"/>
{errors?.reason && <p>{errors.reason}</p>}

<input type="submit"></input>
</Form>
</>
);
}
22 changes: 22 additions & 0 deletions resources/js/Pages/Auction/ShowReport.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Title } from "@/Components/Title";
import { Report } from "@/Types/report";

type Props = {
report: Report,
}

export function Reports({report}: Props) {
return (
<div className='w-full p-4 mt-5 mx-auto md:px-10'>
<Title type='h2'>Szczegóły zgłoszenia</Title>

<div><strong>ID:</strong> {report.id}</div>
<div><strong>Reporter:</strong> {report.reporter?.email || "N/A"}</div>
<div><strong>Auction:</strong> {report.auction?.name || "N/A"}</div>
<div><strong>Reason:</strong> {report.reason || "Brak"}</div>
<div><strong>Resolved At:</strong> {report.resolvedAt || "Nie rozwiązano"}</div>
<div><strong>Created At:</strong> {report.createdAt}</div>
<div><strong>Updated At:</strong> {report.updatedAt}</div>
</div>
);
}
12 changes: 12 additions & 0 deletions resources/js/Types/report.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { User } from "./user";
import { Auction } from "./auction";

export type Report = {
id: number;
reporter: User;
auction: Auction;
reason: string;
resolvedAt: string;
createdAt: string,
updatedAt: string,
}
5 changes: 5 additions & 0 deletions routes/web.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Inertia\Response;
use Otoszroto\Enums\Permission;
use Otoszroto\Http\Controllers\Auction\AuctionController;
use Otoszroto\Http\Controllers\Auction\ReportController;
use Otoszroto\Http\Controllers\Auth\ForgotPasswordController;
use Otoszroto\Http\Controllers\Auth\LoginController;
use Otoszroto\Http\Controllers\Auth\LogoutController;
Expand Down Expand Up @@ -41,6 +42,10 @@
Route::patch("/auctions/{auction}", [AuctionController::class, "update"])->name("auctions.update");
Route::patch("/auctions/{auction}/finish", [AuctionController::class, "finish"])->name("auctions.finish");
Route::patch("/auctions/{auction}/cancel", [AuctionController::class, "cancel"])->name("auctions.cancel");
Route::get("/auctions/{auction}/report", [ReportController::class, "create"])->name("auctions.report.create");
Route::post("/auctions/{auction}/report", [ReportController::class, "store"])->name("auctions.report.store");
Route::get("/reports", [ReportController::class, "index"])->name("reports.index")->middleware([Authorize::using(Permission::ManageReports)]);
Route::get("/reports/{report}", [ReportController::class, "show"])->name("reports.show")->middleware([Authorize::using(Permission::ManageReports)]);
});

Route::get("/auctions/{auction}", [AuctionController::class, "show"])->name("auctions.show");