fix: team permissions, transactions, form sentinels and review polish

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Doar Mihai
2026-10-17 16:12:31 +03:00
co-authored by Claude Sonnet 5.5
parent c4e6173e46
commit 231123f641
8 changed files with 343 additions and 57 deletions
@@ -18,7 +18,7 @@
@keydown.arrow-left.window="open && prev()"
{{ $attributes }}>
<div class="grid grid-cols-1 sm:grid-cols-3 gap-2">
<button type="button" @click="show(0)" class="sm:col-span-2 sm:row-span-3 block overflow-hidden rounded-lg border border-gray-200 dark:border-gray-700">
<button type="button" @click="show(0)" class="{{ $tiles->isEmpty() ? 'sm:col-span-3' : 'sm:col-span-2 sm:row-span-3' }} block overflow-hidden rounded-lg border border-gray-200 dark:border-gray-700">
<img src="{{ $urls[0] }}" alt="{{ $product->title }} screenshot 1" class="w-full h-full object-cover aspect-video sm:aspect-auto">
</button>
@foreach($tiles as $i => $shot)
@@ -1,7 +1,7 @@
@props(['plans' => []])
@php
$initial = collect(old('plans', $plans))->map(fn ($p) => [
$initial = collect(old('plans_present') ? old('plans', []) : $plans)->map(fn ($p) => [
'name' => $p['name'] ?? '',
'price' => $p['price'] ?? '',
'period' => $p['period'] ?? 'monthly',
@@ -12,6 +12,7 @@
<!-- Pricing plans -->
<div x-data="{ plans: @js($initial) }">
<input type="hidden" name="plans_present" value="1">
<label class="block text-sm font-medium text-gray-700">Pricing plans</label>
<div class="mt-2 space-y-3">
<template x-for="(plan, i) in plans" :key="i">
@@ -1,7 +1,7 @@
@props(['members' => []])
@props(['members' => [], 'readonly' => false])
@php
$initial = collect(old('members', collect($members)->map(fn ($m) => [
$initial = collect(old('members_present') ? old('members', []) : (collect($members)->map(fn ($m) => [
'user_id' => $m->id,
'name' => $m->name,
'role' => $m->pivot->role,
@@ -14,6 +14,19 @@
@endphp
<!-- Team members -->
@if($readonly)
<div>
<label class="block text-sm font-medium text-gray-700">Team members</label>
<p class="mt-1 text-sm text-gray-500">Only the submitter or an admin can change the team.</p>
<ul class="mt-2 space-y-1">
@forelse($initial as $m)
<li class="text-sm text-gray-900">{{ $m['name'] }} <span class="text-gray-500">- {{ $m['role'] }}</span></li>
@empty
<li class="text-sm text-gray-500">No team members.</li>
@endforelse
</ul>
</div>
@else
<div x-data="{
members: @js($initial),
q: '',
@@ -32,6 +45,7 @@
this.q = ''; this.results = [];
}
}">
<input type="hidden" name="members_present" value="1">
<label class="block text-sm font-medium text-gray-700">Team members</label>
<div class="relative mt-2">
<input type="text" x-model="q" @input="search()" placeholder="Search users by name" autocomplete="off" class="{{ $input }}">
@@ -45,6 +59,7 @@
<template x-for="(member, i) in members" :key="member.user_id">
<div class="grid grid-cols-1 sm:grid-cols-12 gap-2 p-3 border border-gray-200 rounded-md items-center">
<input type="hidden" :name="`members[${i}][user_id]`" :value="member.user_id">
<input type="hidden" :name="`members[${i}][name]`" :value="member.name">
<span class="sm:col-span-4 text-sm text-gray-900" x-text="member.name"></span>
<input type="text" :name="`members[${i}][role]`" x-model="member.role" placeholder="Role (e.g. Designer)" maxlength="100" class="{{ $input }} sm:col-span-7">
<button type="button" @click="members.splice(i, 1)" class="sm:col-span-1 text-sm text-red-600 hover:text-red-800">Remove</button>
@@ -58,3 +73,4 @@
<p class="mt-2 text-sm text-red-600">{{ $message }}</p>
@enderror
</div>
@endif
+1 -1
View File
@@ -253,7 +253,7 @@
<x-product.plans-form :plans="$product->pricingPlans->toArray()" />
<x-product.team-form :members="$product->members" />
<x-product.team-form :members="$product->members" :readonly="! (auth()->id() === $product->user_id || auth()->user()->isAdmin())" />
<!-- Info Alert -->
<div class="rounded-md bg-blue-50 p-4">