Linted content and add sail plus lint
tests / ci (8.4) (push) Has been cancelled
tests / ci (8.5) (push) Has been cancelled
linter / quality (push) Has been cancelled

This commit is contained in:
Shaun Collins
2026-02-23 16:02:12 +00:00
committed by shaun collins
parent fdd3c55323
commit 52725fe2c4
33 changed files with 1274 additions and 35 deletions
+13 -6
View File
@@ -1,24 +1,31 @@
# Define the app variable based on the existence of vendor/bin/sail
app = $(if $(wildcard vendor/bin/sail), vendor/bin/sail, php)
lint: lint:
vendor/bin/sail pint $(app) pint
npm run lint
build: build:
npm run build npm run build
dev: dev:
npm run dev npm run dev
up: up:
vendor/bin/sail up -d $(app) up -d
down: down:
vendor/bin/sail down $(app) down
install: install:
vendor/bin/sail composer install $(app) composer install
npm install npm install
migrate: migrate:
vendor/bin/sail artisan migrate $(app) artisan migrate
rollback: rollback:
vendor/bin/sail artisan migrate:rollback $(app) artisan migrate:rollback
tinker:
$(app) artisan tinker
+13
View File
@@ -0,0 +1,13 @@
<?php
namespace App\Models\Traits;
use Illuminate\Database\Eloquent\Builder;
trait HasActive
{
public function scopeActive(Builder $builder): void
{
$builder->where('is_active', true);
}
}
+11
View File
@@ -0,0 +1,11 @@
<?php
namespace App\Models\Traits;
trait HasTableName
{
public static function tableName(): string
{
return (new static)->getTable();
}
}
+1 -1
View File
@@ -21,7 +21,7 @@
"fakerphp/faker": "^1.23", "fakerphp/faker": "^1.23",
"fruitcake/laravel-debugbar": "^4.0", "fruitcake/laravel-debugbar": "^4.0",
"laravel/pail": "^1.2.2", "laravel/pail": "^1.2.2",
"laravel/pint": "^1.24", "laravel/pint": "^1.27",
"laravel/sail": "^1.53", "laravel/sail": "^1.53",
"mockery/mockery": "^1.6", "mockery/mockery": "^1.6",
"nunomaduro/collision": "^8.6", "nunomaduro/collision": "^8.6",
Generated
+1 -1
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "a10577048ae0aaa72d0311c170e12de7", "content-hash": "6d5d1269056f3f38d1699989ebf25c1d",
"packages": [ "packages": [
{ {
"name": "bacon/bacon-qr-code", "name": "bacon/bacon-qr-code",
+1204
View File
File diff suppressed because it is too large Load Diff
+2
View File
@@ -28,9 +28,11 @@
"typescript": "^5.2.2", "typescript": "^5.2.2",
"typescript-eslint": "^8.23.0", "typescript-eslint": "^8.23.0",
"vite": "^7.0.4", "vite": "^7.0.4",
"vite-plugin-vue-devtools": "^8.0.6",
"vue-tsc": "^2.2.4" "vue-tsc": "^2.2.4"
}, },
"dependencies": { "dependencies": {
"@fortawesome/fontawesome-free": "^7.2.0",
"@inertiajs/vue3": "^2.3.7", "@inertiajs/vue3": "^2.3.7",
"@vueuse/core": "^12.8.2", "@vueuse/core": "^12.8.2",
"class-variance-authority": "^0.7.1", "class-variance-authority": "^0.7.1",
+1 -1
View File
@@ -35,8 +35,8 @@ import UserMenuContent from '@/components/UserMenuContent.vue';
import { useCurrentUrl } from '@/composables/useCurrentUrl'; import { useCurrentUrl } from '@/composables/useCurrentUrl';
import { getInitials } from '@/composables/useInitials'; import { getInitials } from '@/composables/useInitials';
import { toUrl } from '@/lib/utils'; import { toUrl } from '@/lib/utils';
import type { BreadcrumbItem, NavItem } from '@/types';
import { dashboard } from '@/routes'; import { dashboard } from '@/routes';
import type { BreadcrumbItem, NavItem } from '@/types';
type Props = { type Props = {
breadcrumbs?: BreadcrumbItem[]; breadcrumbs?: BreadcrumbItem[];
+1 -1
View File
@@ -13,9 +13,9 @@ import {
SidebarMenuButton, SidebarMenuButton,
SidebarMenuItem, SidebarMenuItem,
} from '@/components/ui/sidebar'; } from '@/components/ui/sidebar';
import { dashboard } from '@/routes';
import { type NavItem } from '@/types'; import { type NavItem } from '@/types';
import AppLogo from './AppLogo.vue'; import AppLogo from './AppLogo.vue';
import { dashboard } from '@/routes';
const mainNavItems: NavItem[] = [ const mainNavItems: NavItem[] = [
{ {
+1 -1
View File
@@ -1,6 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { Form } from '@inertiajs/vue3'; import { Form } from '@inertiajs/vue3';
import { useTemplateRef } from 'vue'; import { useTemplateRef } from 'vue';
import ProfileController from '@/actions/App/Http/Controllers/Settings/ProfileController';
import Heading from '@/components/Heading.vue'; import Heading from '@/components/Heading.vue';
import InputError from '@/components/InputError.vue'; import InputError from '@/components/InputError.vue';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
@@ -16,7 +17,6 @@ import {
} from '@/components/ui/dialog'; } from '@/components/ui/dialog';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label'; import { Label } from '@/components/ui/label';
import ProfileController from '@/actions/App/Http/Controllers/Settings/ProfileController';
const passwordInput = useTemplateRef('passwordInput'); const passwordInput = useTemplateRef('passwordInput');
</script> </script>
@@ -21,8 +21,8 @@ import {
import { Spinner } from '@/components/ui/spinner'; import { Spinner } from '@/components/ui/spinner';
import { useAppearance } from '@/composables/useAppearance'; import { useAppearance } from '@/composables/useAppearance';
import { useTwoFactorAuth } from '@/composables/useTwoFactorAuth'; import { useTwoFactorAuth } from '@/composables/useTwoFactorAuth';
import type { TwoFactorConfigContent } from '@/types';
import { confirm } from '@/routes/two-factor'; import { confirm } from '@/routes/two-factor';
import type { TwoFactorConfigContent } from '@/types';
type Props = { type Props = {
requiresConfirmation: boolean; requiresConfirmation: boolean;
+1 -1
View File
@@ -8,9 +8,9 @@ import {
DropdownMenuSeparator, DropdownMenuSeparator,
} from '@/components/ui/dropdown-menu'; } from '@/components/ui/dropdown-menu';
import UserInfo from '@/components/UserInfo.vue'; import UserInfo from '@/components/UserInfo.vue';
import type { User } from '@/types';
import { logout } from '@/routes'; import { logout } from '@/routes';
import { edit } from '@/routes/profile'; import { edit } from '@/routes/profile';
import type { User } from '@/types';
type Props = { type Props = {
user: User; user: User;
+1 -1
View File
@@ -5,11 +5,11 @@ import { Button } from '@/components/ui/button';
import { Separator } from '@/components/ui/separator'; import { Separator } from '@/components/ui/separator';
import { useCurrentUrl } from '@/composables/useCurrentUrl'; import { useCurrentUrl } from '@/composables/useCurrentUrl';
import { toUrl } from '@/lib/utils'; import { toUrl } from '@/lib/utils';
import { type NavItem } from '@/types';
import { edit as editAppearance } from '@/routes/appearance'; import { edit as editAppearance } from '@/routes/appearance';
import { edit as editProfile } from '@/routes/profile'; import { edit as editProfile } from '@/routes/profile';
import { show } from '@/routes/two-factor'; import { show } from '@/routes/two-factor';
import { edit as editPassword } from '@/routes/user-password'; import { edit as editPassword } from '@/routes/user-password';
import { type NavItem } from '@/types';
const sidebarNavItems: NavItem[] = [ const sidebarNavItems: NavItem[] = [
{ {
+1 -1
View File
@@ -1,9 +1,9 @@
<script setup lang="ts"> <script setup lang="ts">
import { Head } from '@inertiajs/vue3'; import { Head } from '@inertiajs/vue3';
import AppLayout from '@/layouts/AppLayout.vue'; import AppLayout from '@/layouts/AppLayout.vue';
import { dashboard } from '@/routes';
import { type BreadcrumbItem } from '@/types'; import { type BreadcrumbItem } from '@/types';
import PlaceholderPattern from '../components/PlaceholderPattern.vue'; import PlaceholderPattern from '../components/PlaceholderPattern.vue';
import { dashboard } from '@/routes';
const breadcrumbs: BreadcrumbItem[] = [ const breadcrumbs: BreadcrumbItem[] = [
{ {
@@ -10,8 +10,8 @@ import {
InputOTPSlot, InputOTPSlot,
} from '@/components/ui/input-otp'; } from '@/components/ui/input-otp';
import AuthLayout from '@/layouts/AuthLayout.vue'; import AuthLayout from '@/layouts/AuthLayout.vue';
import type { TwoFactorConfigContent } from '@/types';
import { store } from '@/routes/two-factor/login'; import { store } from '@/routes/two-factor/login';
import type { TwoFactorConfigContent } from '@/types';
const authConfigContent = computed<TwoFactorConfigContent>(() => { const authConfigContent = computed<TwoFactorConfigContent>(() => {
if (showRecoveryInput.value) { if (showRecoveryInput.value) {
+1 -1
View File
@@ -4,8 +4,8 @@ import AppearanceTabs from '@/components/AppearanceTabs.vue';
import Heading from '@/components/Heading.vue'; import Heading from '@/components/Heading.vue';
import AppLayout from '@/layouts/AppLayout.vue'; import AppLayout from '@/layouts/AppLayout.vue';
import SettingsLayout from '@/layouts/settings/Layout.vue'; import SettingsLayout from '@/layouts/settings/Layout.vue';
import { type BreadcrumbItem } from '@/types';
import { edit } from '@/routes/appearance'; import { edit } from '@/routes/appearance';
import { type BreadcrumbItem } from '@/types';
const breadcrumbItems: BreadcrumbItem[] = [ const breadcrumbItems: BreadcrumbItem[] = [
{ {
+2 -2
View File
@@ -1,5 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { Form, Head } from '@inertiajs/vue3'; import { Form, Head } from '@inertiajs/vue3';
import PasswordController from '@/actions/App/Http/Controllers/Settings/PasswordController';
import Heading from '@/components/Heading.vue'; import Heading from '@/components/Heading.vue';
import InputError from '@/components/InputError.vue'; import InputError from '@/components/InputError.vue';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
@@ -7,9 +8,8 @@ import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label'; import { Label } from '@/components/ui/label';
import AppLayout from '@/layouts/AppLayout.vue'; import AppLayout from '@/layouts/AppLayout.vue';
import SettingsLayout from '@/layouts/settings/Layout.vue'; import SettingsLayout from '@/layouts/settings/Layout.vue';
import { type BreadcrumbItem } from '@/types';
import PasswordController from '@/actions/App/Http/Controllers/Settings/PasswordController';
import { edit } from '@/routes/user-password'; import { edit } from '@/routes/user-password';
import { type BreadcrumbItem } from '@/types';
const breadcrumbItems: BreadcrumbItem[] = [ const breadcrumbItems: BreadcrumbItem[] = [
{ {
+2 -2
View File
@@ -1,5 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { Form, Head, Link, usePage } from '@inertiajs/vue3'; import { Form, Head, Link, usePage } from '@inertiajs/vue3';
import ProfileController from '@/actions/App/Http/Controllers/Settings/ProfileController';
import DeleteUser from '@/components/DeleteUser.vue'; import DeleteUser from '@/components/DeleteUser.vue';
import Heading from '@/components/Heading.vue'; import Heading from '@/components/Heading.vue';
import InputError from '@/components/InputError.vue'; import InputError from '@/components/InputError.vue';
@@ -8,10 +9,9 @@ import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label'; import { Label } from '@/components/ui/label';
import AppLayout from '@/layouts/AppLayout.vue'; import AppLayout from '@/layouts/AppLayout.vue';
import SettingsLayout from '@/layouts/settings/Layout.vue'; import SettingsLayout from '@/layouts/settings/Layout.vue';
import { type BreadcrumbItem } from '@/types';
import ProfileController from '@/actions/App/Http/Controllers/Settings/ProfileController';
import { edit } from '@/routes/profile'; import { edit } from '@/routes/profile';
import { send } from '@/routes/verification'; import { send } from '@/routes/verification';
import { type BreadcrumbItem } from '@/types';
type Props = { type Props = {
mustVerifyEmail: boolean; mustVerifyEmail: boolean;
+1 -1
View File
@@ -10,8 +10,8 @@ import { Button } from '@/components/ui/button';
import { useTwoFactorAuth } from '@/composables/useTwoFactorAuth'; import { useTwoFactorAuth } from '@/composables/useTwoFactorAuth';
import AppLayout from '@/layouts/AppLayout.vue'; import AppLayout from '@/layouts/AppLayout.vue';
import SettingsLayout from '@/layouts/settings/Layout.vue'; import SettingsLayout from '@/layouts/settings/Layout.vue';
import type { BreadcrumbItem } from '@/types';
import { disable, enable, show } from '@/routes/two-factor'; import { disable, enable, show } from '@/routes/two-factor';
import type { BreadcrumbItem } from '@/types';
type Props = { type Props = {
requiresConfirmation?: boolean; requiresConfirmation?: boolean;
+1 -1
View File
@@ -81,4 +81,4 @@ test('users are rate limited', function () {
]); ]);
$response->assertTooManyRequests(); $response->assertTooManyRequests();
}); });
+1 -1
View File
@@ -92,4 +92,4 @@ test('already verified user visiting verification link is redirected without fir
Event::assertNotDispatched(Verified::class); Event::assertNotDispatched(Verified::class);
expect($user->fresh()->hasVerifiedEmail())->toBeTrue(); expect($user->fresh()->hasVerifiedEmail())->toBeTrue();
}); });
@@ -19,4 +19,4 @@ test('password confirmation requires authentication', function () {
$response = $this->get(route('password.confirm')); $response = $this->get(route('password.confirm'));
$response->assertRedirect(route('login')); $response->assertRedirect(route('login'));
}); });
+1 -1
View File
@@ -70,4 +70,4 @@ test('password cannot be reset with invalid token', function () {
]); ]);
$response->assertSessionHasErrors('email'); $response->assertSessionHasErrors('email');
}); });
+1 -1
View File
@@ -16,4 +16,4 @@ test('new users can register', function () {
$this->assertAuthenticated(); $this->assertAuthenticated();
$response->assertRedirect(route('dashboard', absolute: false)); $response->assertRedirect(route('dashboard', absolute: false));
}); });
@@ -42,4 +42,4 @@ test('two factor challenge can be rendered', function () {
->assertInertia(fn (Assert $page) => $page ->assertInertia(fn (Assert $page) => $page
->component('auth/TwoFactorChallenge') ->component('auth/TwoFactorChallenge')
); );
}); });
@@ -26,4 +26,4 @@ test('does not send verification notification if email is verified', function ()
->assertRedirect(route('dashboard', absolute: false)); ->assertRedirect(route('dashboard', absolute: false));
Notification::assertNothingSent(); Notification::assertNothingSent();
}); });
+1 -1
View File
@@ -13,4 +13,4 @@ test('authenticated users can visit the dashboard', function () {
$response = $this->get(route('dashboard')); $response = $this->get(route('dashboard'));
$response->assertOk(); $response->assertOk();
}); });
+1 -1
View File
@@ -4,4 +4,4 @@ test('returns a successful response', function () {
$response = $this->get(route('home')); $response = $this->get(route('home'));
$response->assertOk(); $response->assertOk();
}); });
@@ -47,4 +47,4 @@ test('correct password must be provided to update password', function () {
$response $response
->assertSessionHasErrors('current_password') ->assertSessionHasErrors('current_password')
->assertRedirect(route('user-password.edit')); ->assertRedirect(route('user-password.edit'));
}); });
+1 -1
View File
@@ -82,4 +82,4 @@ test('correct password must be provided to delete account', function () {
->assertRedirect(route('profile.edit')); ->assertRedirect(route('profile.edit'));
expect($user->fresh())->not->toBeNull(); expect($user->fresh())->not->toBeNull();
}); });
@@ -76,4 +76,4 @@ test('two factor settings page returns forbidden response when two factor is dis
->withSession(['auth.password_confirmed_at' => time()]) ->withSession(['auth.password_confirmed_at' => time()])
->get(route('two-factor.show')) ->get(route('two-factor.show'))
->assertForbidden(); ->assertForbidden();
}); });
+1 -1
View File
@@ -2,4 +2,4 @@
test('that true is true', function () { test('that true is true', function () {
expect(true)->toBeTrue(); expect(true)->toBeTrue();
}); });
+2
View File
@@ -3,9 +3,11 @@ import tailwindcss from '@tailwindcss/vite';
import vue from '@vitejs/plugin-vue'; import vue from '@vitejs/plugin-vue';
import laravel from 'laravel-vite-plugin'; import laravel from 'laravel-vite-plugin';
import { defineConfig } from 'vite'; import { defineConfig } from 'vite';
import vueDevTools from 'vite-plugin-vue-devtools'
export default defineConfig({ export default defineConfig({
plugins: [ plugins: [
vueDevTools(),
laravel({ laravel({
input: ['resources/js/app.ts'], input: ['resources/js/app.ts'],
ssr: 'resources/js/ssr.ts', ssr: 'resources/js/ssr.ts',