diff --git a/Dockerfile b/Dockerfile index b7a2960..b76f5be 100644 --- a/Dockerfile +++ b/Dockerfile @@ -52,16 +52,8 @@ WORKDIR /var/www FROM php_base AS build ARG VITE_APP_VERSION=local -ARG VITE_REVERB_APP_KEY -ARG VITE_REVERB_HOST -ARG VITE_REVERB_PORT -ARG VITE_REVERB_SCHEME -ENV VITE_APP_VERSION=${VITE_APP_VERSION} \ - VITE_REVERB_APP_KEY=${VITE_REVERB_APP_KEY} \ - VITE_REVERB_HOST=${VITE_REVERB_HOST} \ - VITE_REVERB_PORT=${VITE_REVERB_PORT} \ - VITE_REVERB_SCHEME=${VITE_REVERB_SCHEME} +ENV VITE_APP_VERSION=${VITE_APP_VERSION} COPY --from=node_binary /usr/local/ /usr/local/ COPY . /var/www diff --git a/app/Concerns/ReservedSlugs.php b/app/Concerns/ReservedSlugs.php new file mode 100644 index 0000000..5fc96a8 --- /dev/null +++ b/app/Concerns/ReservedSlugs.php @@ -0,0 +1,27 @@ +reservedSlugs()); + } + + public function reservedSlugs(): array + { + return [ + 'index', + 'edit', + 'update', + 'create', + 'store', + 'delete', + 'destroy', + 'revoke', + 'invite', + 'accept', + ]; + } +} diff --git a/app/Http/Controllers/TeamController.php b/app/Http/Controllers/TeamController.php index 3a88786..1028547 100644 --- a/app/Http/Controllers/TeamController.php +++ b/app/Http/Controllers/TeamController.php @@ -2,69 +2,73 @@ namespace App\Http\Controllers; +use App\Concerns\ReservedSlugs; use App\Enums\TeamMemberRole; use App\Http\Requests\StoreTeamRequest; use App\Http\Requests\UpdateTeamRequest; use App\Http\Resources\TeamInviteResource; use App\Http\Resources\TeamResource; use App\Models\Team; +use Illuminate\Http\JsonResponse; +use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\Support\Arr; use Illuminate\Support\Facades\DB; +use Illuminate\Support\Str; use Inertia\Inertia; -use Str; +use Inertia\Response; class TeamController extends Controller { + + use ReservedSlugs; + /** * Display a listing of the resource. */ - public function index(Request $request) + public function index(Request $request): Response { return Inertia::render('team/Index', [ - 'teams' => TeamResource::collection(Team::visibleTo(auth()->user())->get())->resolve($request), + 'teams' => TeamResource::collection(Team::visibleTo($request->user())->with('members')->get())->resolve($request), ]); } - public function show(Request $request, Team $team) + public function show(Request $request, Team $team): Response { - $teamManager = auth()->user()->can('manage', $team); + $teamManager = $request->user()->can('manage', $team); + $team->load('members'); return Inertia::render('team/Show', [ 'team' => TeamResource::make($team)->resolve($request), 'canManageTeam' => $teamManager, ] + ($teamManager ? [ - 'teamInvites' => TeamInviteResource::collection($team->invites)->resolve($request), + 'teamInvites' => TeamInviteResource::collection($team->invites()->with('invitedBy')->get())->resolve($request), ] : [])); } /** * Store a newly created resource in storage. */ - public function store(StoreTeamRequest $request) + public function store(StoreTeamRequest $request): RedirectResponse { - $validated = $request->validated(); - try { - DB::transaction(function () use ($validated) { - $team = Team::create($validated); - $team->members()->attach( - request()->user()->id, - ['role' => TeamMemberRole::Admin] - ); + DB::transaction(function () use ($request): void { + $team = Team::create($request->validated()); + $team->members()->attach($request->user(), ['role' => TeamMemberRole::Admin]); }); - Inertia::flash('success', 'Team successfully created.'); - - return to_route('teams.index'); } catch (\Exception $exception) { + report($exception); Inertia::flash('error', 'Team could not be created.'); - DB::rollBack(); - return back(); + return back()->withInput(); } + + Inertia::flash('success', 'Team successfully created.'); + + return to_route('teams.index'); } - public function create() + public function create(): Response { return Inertia::render('team/Create'); } @@ -72,7 +76,7 @@ class TeamController extends Controller /** * Show the form for editing the specified resource. */ - public function edit(Request $request, Team $team) + public function edit(Request $request, Team $team): Response { return Inertia::render('team/Edit', [ 'team' => TeamResource::make($team)->resolve($request), @@ -82,25 +86,23 @@ class TeamController extends Controller /** * Update the specified resource in storage. */ - public function update(UpdateTeamRequest $request, Team $team) + public function update(UpdateTeamRequest $request, Team $team): RedirectResponse { - $validated = $request->validated(); - try { - DB::transaction(function () use ($validated, $team) { - $team->update($validated); - }); - Inertia::flash('success', 'Team successfully updated.'); - + $team->update($request->validated()); } catch (\Exception $exception) { + report($exception); Inertia::flash('error', 'Team could not be updated.'); - DB::rollBack(); + + return back()->withInput(); } + Inertia::flash('success', 'Team successfully updated.'); + return to_route('teams.show', $team); } - public function nameToSlug(Request $request) + public function nameToSlug(Request $request): JsonResponse { $validated = $request->validate([ 'name' => 'required|string|max:255', @@ -114,7 +116,7 @@ class TeamController extends Controller return response()->json([ 'name' => $name, 'slug' => $slug, - 'taken' => $slug !== $ignoredSlug && Team::whereSlug($slug)->exists(), + 'taken' => $this->isReserved($slug) || ($slug !== $ignoredSlug && Team::whereSlug($slug)->exists()), ]); } @@ -134,25 +136,25 @@ class TeamController extends Controller Inertia::flash('success', 'User invited to your team.'); } - public function revokeInvite(Request $request, Team $team) + public function revokeInvite(Request $request, Team $team): RedirectResponse { $validated = $request->validate([ - 'email' => 'required|email|max:255|exists:team_invites,invited_email', + 'email' => 'required|email|max:255', ]); - abort_unless(auth()->user()->can('manage', $team), 403); - - $teamInvite = $team->invites()->whereInvitedEmail(Arr::get($validated, 'email'))->firstOrFail(); + $teamInvite = $team->invites()->whereInvitedEmail(Arr::get($validated,'email'))->firstOrFail(); try { - DB::transaction(function () use ($teamInvite) { - $teamInvite->delete(); - }); - Inertia::flash('success', 'successfully deleted user invite.'); - } catch (\Throwable $e) { + $teamInvite->delete(); + } catch (\Exception $exception) { + report($exception); Inertia::flash('error', 'could not delete user invite.'); - DB::rollBack(); + + return to_route('teams.show', $team); } + Inertia::flash('success', 'successfully deleted user invite.'); + + return to_route('teams.show', $team); } } diff --git a/app/Http/Requests/StoreTeamRequest.php b/app/Http/Requests/StoreTeamRequest.php index 3352198..4d7f464 100644 --- a/app/Http/Requests/StoreTeamRequest.php +++ b/app/Http/Requests/StoreTeamRequest.php @@ -2,12 +2,17 @@ namespace App\Http\Requests; +use App\Concerns\ReservedSlugs; use Illuminate\Contracts\Validation\ValidationRule; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Str; +use Illuminate\Validation\Rule; class StoreTeamRequest extends FormRequest { + + use ReservedSlugs; + /** * Get the validation rules that apply to the request. * @@ -17,7 +22,7 @@ class StoreTeamRequest extends FormRequest { return [ 'name' => ['required', 'string', 'max:255'], - 'slug' => ['required', 'string', 'max:255', 'unique:teams,slug'], + 'slug' => ['required', 'string', 'max:255', Rule::notIn($this->reservedSlugs()), Rule::unique('teams', 'slug')], 'require_2fa' => ['required', 'boolean'], ]; } @@ -25,9 +30,8 @@ class StoreTeamRequest extends FormRequest public function messages(): array { return [ - 'slug.string' => '', - 'slug.required' => '', - 'slug.max' => '', + 'slug.required' => 'The name must contain letters or numbers.', + 'slug.not_in' => 'This name is reserved.', 'slug.unique' => 'The name has already been taken.', ]; } @@ -35,7 +39,7 @@ class StoreTeamRequest extends FormRequest protected function prepareForValidation(): void { $this->merge([ - 'slug' => Str::slug($this->name), + 'slug' => is_string($this->input('name')) ? Str::slug($this->input('name')) : null, ]); } } diff --git a/app/Http/Requests/UpdateTeamRequest.php b/app/Http/Requests/UpdateTeamRequest.php index 5263aa6..3f7b31d 100644 --- a/app/Http/Requests/UpdateTeamRequest.php +++ b/app/Http/Requests/UpdateTeamRequest.php @@ -2,12 +2,15 @@ namespace App\Http\Requests; +use App\Concerns\ReservedSlugs; use Illuminate\Contracts\Validation\ValidationRule; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Str; +use Illuminate\Validation\Rule; class UpdateTeamRequest extends FormRequest { + use ReservedSlugs; /** * Get the validation rules that apply to the request. * @@ -16,8 +19,8 @@ class UpdateTeamRequest extends FormRequest public function rules(): array { return [ - 'name' => ['nullable', 'string', 'max:255'], - 'slug' => ['nullable', 'required_with:name', 'string', 'max:255', 'unique:teams,slug,'.$this->route('team')->id], + 'name' => ['sometimes', 'required', 'string', 'max:255'], + 'slug' => [Rule::excludeIf(! $this->has('name')), 'required', 'string', 'max:255', Rule::notIn($this->reservedSlugs()), Rule::unique('teams', 'slug')->ignore($this->route('team'))], 'require_2fa' => ['required', 'boolean'], ]; } @@ -25,9 +28,8 @@ class UpdateTeamRequest extends FormRequest public function messages(): array { return [ - 'slug.string' => '', - 'slug.required' => '', - 'slug.max' => '', + 'slug.required' => 'The name must contain letters or numbers.', + 'slug.not_in' => 'This name is reserved.', 'slug.unique' => 'The name has already been taken.', ]; } @@ -35,7 +37,7 @@ class UpdateTeamRequest extends FormRequest protected function prepareForValidation(): void { $this->merge([ - 'slug' => Str::slug($this->name), + 'slug' => is_string($this->input('name')) ? Str::slug($this->input('name')) : null, ]); } } diff --git a/app/Http/Resources/TeamInviteResource.php b/app/Http/Resources/TeamInviteResource.php index e0b18ff..28a1596 100644 --- a/app/Http/Resources/TeamInviteResource.php +++ b/app/Http/Resources/TeamInviteResource.php @@ -20,7 +20,6 @@ class TeamInviteResource extends JsonResource { return [ 'invitedEmail' => $this->invited_email, - 'team' => TeamResource::make($this->team)->resolve($request), 'invitedBy' => UserResource::make($this->invitedBy)->resolve($request), 'invitedAt' => $this->created_at->toDateTimeString(), ]; diff --git a/app/Http/Resources/UserResource.php b/app/Http/Resources/UserResource.php index 2f40320..a07caca 100644 --- a/app/Http/Resources/UserResource.php +++ b/app/Http/Resources/UserResource.php @@ -21,7 +21,7 @@ class UserResource extends JsonResource return [ 'name' => $this->name, 'email' => $this->email, - 'has_multi_factor' => $this->hasVerifiedEmail() || $this->hasEnabledTwoFactorAuthentication(), + 'has_multi_factor' => $this->hasEnabledTwoFactorAuthentication(), ]; } } diff --git a/app/Models/Team.php b/app/Models/Team.php index 621530a..c6b5c2d 100644 --- a/app/Models/Team.php +++ b/app/Models/Team.php @@ -2,9 +2,11 @@ namespace App\Models; +use Carbon\CarbonImmutable; use Illuminate\Database\Eloquent\Attributes\Fillable; use Illuminate\Database\Eloquent\Attributes\Scope; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; @@ -13,24 +15,26 @@ use Illuminate\Database\Eloquent\Relations\HasMany; * @property int $id * @property string $name * @property string $slug - * @property int $created_by * @property bool $require_2fa - * @property \Carbon\CarbonImmutable|null $created_at - * @property \Carbon\CarbonImmutable|null $updated_at - * @property-read \App\Models\TeamMember|null $pivot - * @property-read \Illuminate\Database\Eloquent\Collection $members + * @property CarbonImmutable|null $created_at + * @property CarbonImmutable|null $updated_at + * @property-read Collection $invites + * @property-read int|null $invites_count + * @property-read TeamMember|null $pivot + * @property-read Collection $members * @property-read int|null $members_count + * * @method static Builder|Team newModelQuery() * @method static Builder|Team newQuery() * @method static Builder|Team query() - * @method static Builder|Team visibleTo(\App\Models\User $user) + * @method static Builder|Team scopeVisibleTo(\App\Models\User $user) * @method static Builder|Team whereCreatedAt($value) - * @method static Builder|Team whereCreatedBy($value) * @method static Builder|Team whereId($value) * @method static Builder|Team whereName($value) * @method static Builder|Team whereRequire2fa($value) * @method static Builder|Team whereSlug($value) * @method static Builder|Team whereUpdatedAt($value) + * * @mixin \Eloquent */ #[Fillable(['name', 'slug', 'require_2fa'])] @@ -43,6 +47,7 @@ class Team extends Model ->withPivot('role') ->withTimestamps(); } + public function invites(): HasMany { return $this->hasMany(TeamInvite::class); diff --git a/app/Models/TeamInvite.php b/app/Models/TeamInvite.php index 5b36eed..66ebe0f 100644 --- a/app/Models/TeamInvite.php +++ b/app/Models/TeamInvite.php @@ -3,15 +3,45 @@ namespace App\Models; use App\Notifications\InviteToTeam; +use Carbon\CarbonImmutable; use Illuminate\Database\Eloquent\Attributes\Fillable; use Illuminate\Database\Eloquent\Attributes\Scope; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Notifications\DatabaseNotification; +use Illuminate\Notifications\DatabaseNotificationCollection; use Illuminate\Notifications\Notifiable; use Illuminate\Notifications\Notification; use Str; +/** + * @property int $id + * @property int $team_id + * @property int $invited_by_user_id + * @property string $invited_email + * @property string $invite_token + * @property CarbonImmutable|null $created_at + * @property CarbonImmutable|null $updated_at + * @property-read User $invitedBy + * @property-read DatabaseNotificationCollection $notifications + * @property-read int|null $notifications_count + * @property-read Team $team + * + * @method static Builder|TeamInvite findByPlainToken(string $token) + * @method static Builder|TeamInvite newModelQuery() + * @method static Builder|TeamInvite newQuery() + * @method static Builder|TeamInvite query() + * @method static Builder|TeamInvite whereCreatedAt($value) + * @method static Builder|TeamInvite whereId($value) + * @method static Builder|TeamInvite whereInviteToken($value) + * @method static Builder|TeamInvite whereInvitedByUserId($value) + * @method static Builder|TeamInvite whereInvitedEmail($value) + * @method static Builder|TeamInvite whereTeamId($value) + * @method static Builder|TeamInvite whereUpdatedAt($value) + * + * @mixin \Eloquent + */ #[Fillable(['team_id', 'invited_by_user_id', 'invited_email'])] class TeamInvite extends Model { diff --git a/app/Models/TeamMember.php b/app/Models/TeamMember.php index b5b496a..45d4de3 100644 --- a/app/Models/TeamMember.php +++ b/app/Models/TeamMember.php @@ -3,15 +3,16 @@ namespace App\Models; use App\Enums\TeamMemberRole; -use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Carbon\CarbonImmutable; use Illuminate\Database\Eloquent\Relations\Pivot; /** * @property int $team_id * @property int $user_id * @property TeamMemberRole $role - * @property \Carbon\CarbonImmutable|null $created_at - * @property \Carbon\CarbonImmutable|null $updated_at + * @property CarbonImmutable|null $created_at + * @property CarbonImmutable|null $updated_at + * * @method static \Illuminate\Database\Eloquent\Builder|TeamMember newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|TeamMember newQuery() * @method static \Illuminate\Database\Eloquent\Builder|TeamMember query() @@ -20,6 +21,7 @@ use Illuminate\Database\Eloquent\Relations\Pivot; * @method static \Illuminate\Database\Eloquent\Builder|TeamMember whereTeamId($value) * @method static \Illuminate\Database\Eloquent\Builder|TeamMember whereUpdatedAt($value) * @method static \Illuminate\Database\Eloquent\Builder|TeamMember whereUserId($value) + * * @mixin \Eloquent */ class TeamMember extends Pivot diff --git a/app/Models/User.php b/app/Models/User.php index 3c199a9..5b7aeee 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -2,37 +2,43 @@ namespace App\Models; -use Illuminate\Contracts\Auth\MustVerifyEmail; +use Carbon\CarbonImmutable; use Database\Factories\UserFactory; +use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Database\Eloquent\Attributes\Fillable; use Illuminate\Database\Eloquent\Attributes\Hidden; +use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Foundation\Auth\User as Authenticatable; +use Illuminate\Notifications\DatabaseNotification; +use Illuminate\Notifications\DatabaseNotificationCollection; use Illuminate\Notifications\Notifiable; use Laravel\Fortify\Contracts\PasskeyUser; use Laravel\Fortify\PasskeyAuthenticatable; use Laravel\Fortify\TwoFactorAuthenticatable; +use Laravel\Passkeys\Passkey; /** * @property int $id * @property string $name * @property string $email - * @property \Carbon\CarbonImmutable|null $email_verified_at + * @property CarbonImmutable|null $email_verified_at * @property string $password - * @property string|null $remember_token - * @property \Carbon\CarbonImmutable|null $created_at - * @property \Carbon\CarbonImmutable|null $updated_at * @property string|null $two_factor_secret * @property string|null $two_factor_recovery_codes - * @property \Carbon\CarbonImmutable|null $two_factor_confirmed_at - * @property-read \Illuminate\Notifications\DatabaseNotificationCollection $notifications + * @property CarbonImmutable|null $two_factor_confirmed_at + * @property string|null $remember_token + * @property CarbonImmutable|null $created_at + * @property CarbonImmutable|null $updated_at + * @property-read DatabaseNotificationCollection $notifications * @property-read int|null $notifications_count - * @property-read \Illuminate\Database\Eloquent\Collection $passkeys + * @property-read Collection $passkeys * @property-read int|null $passkeys_count - * @property-read \App\Models\TeamMember|null $pivot - * @property-read \Illuminate\Database\Eloquent\Collection $teams + * @property-read TeamMember|null $pivot + * @property-read Collection $teams * @property-read int|null $teams_count + * * @method static \Database\Factories\UserFactory factory($count = null, $state = []) * @method static \Illuminate\Database\Eloquent\Builder|User newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|User newQuery() @@ -48,11 +54,12 @@ use Laravel\Fortify\TwoFactorAuthenticatable; * @method static \Illuminate\Database\Eloquent\Builder|User whereTwoFactorRecoveryCodes($value) * @method static \Illuminate\Database\Eloquent\Builder|User whereTwoFactorSecret($value) * @method static \Illuminate\Database\Eloquent\Builder|User whereUpdatedAt($value) + * * @mixin \Eloquent */ #[Fillable(['name', 'email', 'password'])] #[Hidden(['password', 'two_factor_secret', 'two_factor_recovery_codes', 'remember_token'])] -class User extends Authenticatable implements PasskeyUser, MustVerifyEmail +class User extends Authenticatable implements MustVerifyEmail, PasskeyUser { /** @use HasFactory */ use HasFactory, Notifiable, PasskeyAuthenticatable, TwoFactorAuthenticatable; diff --git a/database/factories/TeamFactory.php b/database/factories/TeamFactory.php new file mode 100644 index 0000000..a2ff1a6 --- /dev/null +++ b/database/factories/TeamFactory.php @@ -0,0 +1,22 @@ + */ +class TeamFactory extends Factory +{ + public function definition(): array + { + $name = fake()->unique()->company(); + + return [ + 'name' => $name, + 'slug' => Str::slug($name), + 'require_2fa' => false, + ]; + } +} diff --git a/database/factories/TeamInviteFactory.php b/database/factories/TeamInviteFactory.php new file mode 100644 index 0000000..c755a83 --- /dev/null +++ b/database/factories/TeamInviteFactory.php @@ -0,0 +1,21 @@ + */ +class TeamInviteFactory extends Factory +{ + public function definition(): array + { + return [ + 'team_id' => TeamFactory::new(), + 'invited_by_user_id' => UserFactory::new(), + 'invited_email' => fake()->unique()->safeEmail(), + 'invite_token' => hash('sha256', Str::random(128)), + ]; + } +} diff --git a/database/migrations/2026_09_10_192513_create_teams_table.php b/database/migrations/2026_09_10_192513_create_teams_table.php index 1ad28ad..7544d53 100644 --- a/database/migrations/2026_09_10_192513_create_teams_table.php +++ b/database/migrations/2026_09_10_192513_create_teams_table.php @@ -1,6 +1,5 @@ -import teamRoutes from '@/routes/teams'; +import { useHttp } from '@inertiajs/vue3'; +import { ref, watch } from 'vue'; +import InputError from '@/components/InputError.vue'; +import { Label } from '@/components/ui/label'; +import { Input } from '@/components/ui/input'; +import { nameToSlug } from '@/routes/teams'; -import InputError from "@/components/InputError.vue"; -import {Label} from "@/components/ui/label"; -import {Input} from "@/components/ui/input"; -import {watch} from "vue"; +type TeamSlugRequest = { + name: string; + ignored_slug: string | null; +}; -type nameToSlugResponse = { +type TeamSlugResponse = { name: string; slug: string; taken: boolean; -} +}; -const props = defineProps<{ name: string, ignoredSlug?: string }>() - -const slug = defineModel('slug', { - required: true, -}); -const slugTaken = defineModel('slugTaken', { - required: true, -}); -const slugError = defineModel('slugError', { - required: true, +const props = defineProps<{ + name: string; + ignoredSlug?: string; + error?: string; +}>(); +const slug = defineModel('slug', { required: true }); +const slugTaken = defineModel('slugTaken', { required: true }); +const previewError = ref(''); +const http = useHttp({ + name: '', + ignored_slug: null, }); -watch(() => props.name, (newName) => fetch(teamRoutes.nameToSlug().url, { - method: 'POST', - headers: {'Content-Type': 'application/json'}, - body: JSON.stringify({name: newName, ignored_slug: props.ignoredSlug}) - }).then(async (response) => { - slugError.value = '' - console.info(response) - const body = (await response.json()) as unknown as nameToSlugResponse; - console.info(body) - slug.value = body.slug; - slugTaken.value = body.taken; - if (slugTaken.value) { - slugError.value = 'Der Slug ist bereits vergeben.' - } - }).catch(() => slugError.value = 'Failed to Fetch new slug') -) +watch( + () => props.name, + (name, _previous, onCleanup) => { + let active = true; + slugTaken.value = false; + previewError.value = ''; + const timer = setTimeout(async () => { + if (!name.trim()) { + slug.value = ''; + return; + } + + http.name = name; + http.ignored_slug = props.ignoredSlug ?? null; + + try { + const response = await http.submit(nameToSlug()); + if (active) { + slug.value = response.slug; + slugTaken.value = response.taken; + previewError.value = response.taken + ? 'Der Slug ist bereits vergeben.' + : ''; + } + } catch { + if (active) { + previewError.value = 'Die Slug-Vorschau konnte nicht geladen werden.'; + } + } + }, 250); + + onCleanup(() => { + active = false; + clearTimeout(timer); + http.cancel(); + }); + }, +); - diff --git a/resources/js/pages/team/Create.vue b/resources/js/pages/team/Create.vue index b156d4c..433c540 100644 --- a/resources/js/pages/team/Create.vue +++ b/resources/js/pages/team/Create.vue @@ -1,15 +1,15 @@