further development of the predefinedmutations
This commit is contained in:
parent
ed23bb2a78
commit
11df4ef55c
@ -3,6 +3,7 @@
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Dynamic;
|
||||
use App\Models\Ledger;
|
||||
use App\Models\PredefinedMutation;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Http\Request;
|
||||
@ -15,20 +16,21 @@ class PredefinedMutationController extends Controller
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index(Dynamic $dynamic)
|
||||
public function index(Dynamic $dynamic, Ledger $ledger)
|
||||
{
|
||||
$this->authorize('update', $dynamic);
|
||||
|
||||
return Inertia::render('Dynamics/PredefinedMutations/Index', [
|
||||
return Inertia::render('Ledgers/PredefinedMutations/Index', [
|
||||
'dynamic' => $dynamic,
|
||||
'predefined_mutations' => $dynamic->predefinedMutations()->latest()->get(),
|
||||
'ledger' => $ledger,
|
||||
'predefined_mutations' => $ledger->predefinedMutations()->latest()->get(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*/
|
||||
public function store(Request $request, Dynamic $dynamic)
|
||||
public function store(Request $request, Dynamic $dynamic, Ledger $ledger)
|
||||
{
|
||||
$this->authorize('update', $dynamic);
|
||||
|
||||
@ -36,11 +38,10 @@ class PredefinedMutationController extends Controller
|
||||
'name' => ['required', 'string', 'max:255'],
|
||||
'description' => ['nullable', 'string'],
|
||||
'amount' => ['required', 'integer'],
|
||||
'type' => ['required', 'string', 'in:reward,penalty'],
|
||||
]);
|
||||
|
||||
$dynamic->predefinedMutations()->create($request->all());
|
||||
$ledger->predefinedMutations()->create($request->all());
|
||||
|
||||
return redirect()->route('dynamics.predefined-mutations.index', $dynamic);
|
||||
return redirect()->route('dynamics.ledgers.predefined-mutations.index', [$dynamic, $ledger]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,6 +31,11 @@ class Ledger extends Model
|
||||
return $this->hasMany(Mutation::class);
|
||||
}
|
||||
|
||||
public function predefinedMutations(): HasMany
|
||||
{
|
||||
return $this->hasMany(PredefinedMutation::class);
|
||||
}
|
||||
|
||||
public function media(): \Illuminate\Database\Eloquent\Relations\MorphMany
|
||||
{
|
||||
return $this->morphMany(Media::class, 'mediable');
|
||||
|
||||
@ -11,15 +11,14 @@ class PredefinedMutation extends Model
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'dynamic_id',
|
||||
'ledger_id',
|
||||
'name',
|
||||
'description',
|
||||
'amount',
|
||||
'type',
|
||||
];
|
||||
|
||||
public function dynamic(): BelongsTo
|
||||
public function ledger(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Dynamic::class);
|
||||
return $this->belongsTo(Ledger::class);
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,11 +13,10 @@ return new class extends Migration
|
||||
{
|
||||
Schema::create('predefined_mutations', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('dynamic_id')->constrained()->cascadeOnDelete();
|
||||
$table->foreignId('ledger_id')->constrained()->cascadeOnDelete();
|
||||
$table->string('name');
|
||||
$table->text('description')->nullable();
|
||||
$table->integer('amount');
|
||||
$table->string('type')->default('reward');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
@ -70,12 +70,6 @@ function submit() {
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-8">
|
||||
<InertiaLink :href="route('dynamics.predefined-mutations.index', dynamic.id)" class="c-dynamic-settings__submit-btn">
|
||||
Manage Predefined Mutations
|
||||
</InertiaLink>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -9,12 +9,15 @@ const props = defineProps<{
|
||||
id: number;
|
||||
name: string;
|
||||
};
|
||||
ledger: {
|
||||
id: number;
|
||||
name: string;
|
||||
};
|
||||
predefined_mutations: Array<{
|
||||
id: number;
|
||||
name: string;
|
||||
description: string;
|
||||
amount: number;
|
||||
type: string;
|
||||
}>;
|
||||
}>();
|
||||
|
||||
@ -22,7 +25,6 @@ const form = useForm({
|
||||
name: '',
|
||||
description: '',
|
||||
amount: 0,
|
||||
type: 'reward',
|
||||
});
|
||||
|
||||
const breadcrumbs = [
|
||||
@ -34,14 +36,18 @@ const breadcrumbs = [
|
||||
name: props.dynamic.name,
|
||||
href: route('dynamics.show', props.dynamic.id),
|
||||
},
|
||||
{
|
||||
name: props.ledger.name,
|
||||
href: route('dynamics.ledgers.show', [props.dynamic.id, props.ledger.id]),
|
||||
},
|
||||
{
|
||||
name: 'Predefined Mutations',
|
||||
href: route('dynamics.predefined-mutations.index', props.dynamic.id),
|
||||
href: route('dynamics.ledgers.predefined-mutations.index', [props.dynamic.id, props.ledger.id]),
|
||||
},
|
||||
];
|
||||
|
||||
function submit() {
|
||||
form.post(route('dynamics.predefined-mutations.store', props.dynamic.id), {
|
||||
form.post(route('dynamics.ledgers.predefined-mutations.store', [props.dynamic.id, props.ledger.id]), {
|
||||
onSuccess: () => form.reset(),
|
||||
});
|
||||
}
|
||||
@ -56,7 +62,7 @@ function submit() {
|
||||
<div class="c-predefined-mutations__card">
|
||||
<div class="c-predefined-mutations__body">
|
||||
<h3 class="c-predefined-mutations__title">
|
||||
Predefined Mutations for {{ dynamic.name }}
|
||||
Predefined Mutations for {{ ledger.name }}
|
||||
</h3>
|
||||
|
||||
<div class="c-predefined-mutations__list">
|
||||
@ -133,22 +139,6 @@ function submit() {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="c-predefined-mutations__field">
|
||||
<label
|
||||
for="type"
|
||||
class="c-predefined-mutations__label"
|
||||
>Type</label
|
||||
>
|
||||
<select
|
||||
v-model="form.type"
|
||||
id="type"
|
||||
class="c-predefined-mutations__select"
|
||||
>
|
||||
<option value="reward">Reward</option>
|
||||
<option value="penalty">Penalty</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="c-predefined-mutations__actions">
|
||||
<button
|
||||
type="submit"
|
||||
@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { Head } from '@inertiajs/vue3';
|
||||
import { Head, Link as InertiaLink } from '@inertiajs/vue3';
|
||||
import { useEcho } from '@laravel/echo-vue';
|
||||
import { ref } from 'vue';
|
||||
import { route } from 'ziggy-js';
|
||||
@ -168,13 +168,25 @@ function isOwnerUser(userId: number): boolean {
|
||||
<div class="c-ledger-show__container">
|
||||
<div class="c-ledger-show__card">
|
||||
<div class="c-ledger-show__body">
|
||||
<h3 class="c-ledger-show__title">{{ ledger.name }}</h3>
|
||||
<p class="c-ledger-show__score">
|
||||
Score: {{ ledger.score }}
|
||||
</p>
|
||||
<p class="c-ledger-show__rules">
|
||||
{{ ledger.rules }}
|
||||
</p>
|
||||
<div class="flex flex-col sm:flex-row sm:justify-between sm:items-start gap-4">
|
||||
<div>
|
||||
<h3 class="c-ledger-show__title">{{ ledger.name }}</h3>
|
||||
<p class="c-ledger-show__score">
|
||||
Score: {{ ledger.score }}
|
||||
</p>
|
||||
<p class="c-ledger-show__rules">
|
||||
{{ ledger.rules }}
|
||||
</p>
|
||||
</div>
|
||||
<div v-if="isOwner" class="flex flex-col gap-2">
|
||||
<InertiaLink
|
||||
:href="route('dynamics.ledgers.predefined-mutations.index', [dynamic.id, ledger.id])"
|
||||
class="c-ledger-show__manage-btn"
|
||||
>
|
||||
Predefined Mutations
|
||||
</InertiaLink>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Ledger Alignment Badge / Subtitle -->
|
||||
<div class="c-ledger-show__alignment-wrapper">
|
||||
@ -288,6 +300,10 @@ function isOwnerUser(userId: number): boolean {
|
||||
@apply py-12;
|
||||
}
|
||||
|
||||
.c-ledger-show__manage-btn {
|
||||
@apply inline-flex items-center rounded-md border border-transparent bg-gray-800 px-4 py-2 text-xs font-semibold tracking-widest text-white uppercase transition duration-150 ease-in-out hover:bg-gray-700 focus:bg-gray-700 focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 focus:outline-none active:bg-gray-900 dark:bg-gray-200 dark:text-gray-800 dark:hover:bg-white dark:focus:bg-white dark:focus:ring-offset-gray-800 dark:active:bg-gray-300;
|
||||
}
|
||||
|
||||
.c-ledger-show__container {
|
||||
@apply mx-auto max-w-7xl sm:px-6 lg:px-8;
|
||||
}
|
||||
|
||||
@ -19,7 +19,7 @@ Route::middleware(['auth', 'verified'])->group(function () {
|
||||
Route::get('/dynamics/{dynamic}/ledgers/create', [LedgerController::class, 'create'])->name('dynamics.ledgers.create');
|
||||
Route::resource('dynamics.ledgers', LedgerController::class)->scoped()->except(['create']);
|
||||
|
||||
Route::resource('dynamics.predefined-mutations', \App\Http\Controllers\PredefinedMutationController::class)->scoped();
|
||||
Route::resource('dynamics.ledgers.predefined-mutations', \App\Http\Controllers\PredefinedMutationController::class)->scoped();
|
||||
|
||||
Route::resource('dynamics.ledgers.mutations', MutationController::class)->scoped();
|
||||
|
||||
|
||||
92
tests/Feature/PredefinedMutationTest.php
Normal file
92
tests/Feature/PredefinedMutationTest.php
Normal file
@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
use App\Models\User;
|
||||
use App\Models\Dynamic;
|
||||
use App\Models\Ledger;
|
||||
use App\Models\PredefinedMutation;
|
||||
|
||||
test('owner can view predefined mutations for ledger', function () {
|
||||
$owner = User::factory()->create();
|
||||
$dynamic = Dynamic::factory()->create();
|
||||
$dynamic->participants()->attach($owner->id, ['role' => 'owner']);
|
||||
$ledger = Ledger::factory()->create(['dynamic_id' => $dynamic->id]);
|
||||
|
||||
$predefined = PredefinedMutation::create([
|
||||
'ledger_id' => $ledger->id,
|
||||
'name' => 'Weekly Room Cleaning',
|
||||
'description' => 'Cleaned up the master bedroom',
|
||||
'amount' => 20,
|
||||
]);
|
||||
|
||||
$this->actingAs($owner);
|
||||
|
||||
$response = $this->get(route('dynamics.ledgers.predefined-mutations.index', [$dynamic->id, $ledger->id]));
|
||||
|
||||
$response->assertOk();
|
||||
$response->assertInertia(fn ($page) => $page
|
||||
->component('Ledgers/PredefinedMutations/Index')
|
||||
->where('ledger.id', $ledger->id)
|
||||
->has('predefined_mutations', 1)
|
||||
->where('predefined_mutations.0.name', 'Weekly Room Cleaning')
|
||||
);
|
||||
});
|
||||
|
||||
test('non-owner cannot view predefined mutations for ledger', function () {
|
||||
$owner = User::factory()->create();
|
||||
$participant = User::factory()->create();
|
||||
$dynamic = Dynamic::factory()->create();
|
||||
$dynamic->participants()->attach($owner->id, ['role' => 'owner']);
|
||||
$dynamic->participants()->attach($participant->id, ['role' => 'participant']);
|
||||
$ledger = Ledger::factory()->create(['dynamic_id' => $dynamic->id]);
|
||||
|
||||
$this->actingAs($participant);
|
||||
|
||||
$response = $this->get(route('dynamics.ledgers.predefined-mutations.index', [$dynamic->id, $ledger->id]));
|
||||
|
||||
$response->assertStatus(403);
|
||||
});
|
||||
|
||||
test('owner can create predefined mutations for ledger', function () {
|
||||
$owner = User::factory()->create();
|
||||
$dynamic = Dynamic::factory()->create();
|
||||
$dynamic->participants()->attach($owner->id, ['role' => 'owner']);
|
||||
$ledger = Ledger::factory()->create(['dynamic_id' => $dynamic->id]);
|
||||
|
||||
$this->actingAs($owner);
|
||||
|
||||
$response = $this->post(route('dynamics.ledgers.predefined-mutations.store', [$dynamic->id, $ledger->id]), [
|
||||
'name' => 'Polished mirrors',
|
||||
'description' => 'Mirror polishing in dungeon',
|
||||
'amount' => 15,
|
||||
]);
|
||||
|
||||
$response->assertRedirect();
|
||||
$this->assertDatabaseHas('predefined_mutations', [
|
||||
'ledger_id' => $ledger->id,
|
||||
'name' => 'Polished mirrors',
|
||||
'amount' => 15,
|
||||
]);
|
||||
});
|
||||
|
||||
test('non-owner cannot create predefined mutations for ledger', function () {
|
||||
$owner = User::factory()->create();
|
||||
$participant = User::factory()->create();
|
||||
$dynamic = Dynamic::factory()->create();
|
||||
$dynamic->participants()->attach($owner->id, ['role' => 'owner']);
|
||||
$dynamic->participants()->attach($participant->id, ['role' => 'participant']);
|
||||
$ledger = Ledger::factory()->create(['dynamic_id' => $dynamic->id]);
|
||||
|
||||
$this->actingAs($participant);
|
||||
|
||||
$response = $this->post(route('dynamics.ledgers.predefined-mutations.store', [$dynamic->id, $ledger->id]), [
|
||||
'name' => 'Polished mirrors',
|
||||
'description' => 'Mirror polishing in dungeon',
|
||||
'amount' => 15,
|
||||
]);
|
||||
|
||||
$response->assertStatus(403);
|
||||
$this->assertDatabaseMissing('predefined_mutations', [
|
||||
'ledger_id' => $ledger->id,
|
||||
'name' => 'Polished mirrors',
|
||||
]);
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user