diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 485e0839e..51b624a53 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -34,12 +34,12 @@ jobs: - name: Install Node Dependencies run: npm ci - - name: Build Assets - run: npm run build - - name: Install Dependencies run: composer install --no-interaction --prefer-dist --optimize-autoloader + - name: Build Assets + run: npm run build + - name: Copy Environment File run: cp .env.example .env diff --git a/.gitignore b/.gitignore index 3847c0df4..c625a11f7 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,9 @@ /public/build /public/hot /public/storage +/resources/js/actions +/resources/js/routes +/resources/js/wayfinder /storage/*.key /storage/pail /vendor diff --git a/.prettierignore b/.prettierignore index df954ecde..6b929aea9 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,3 +1,2 @@ resources/js/components/ui/* -resources/js/ziggy.js resources/views/mail/* diff --git a/app/Http/Middleware/HandleInertiaRequests.php b/app/Http/Middleware/HandleInertiaRequests.php index 3af9fd499..bd8901335 100644 --- a/app/Http/Middleware/HandleInertiaRequests.php +++ b/app/Http/Middleware/HandleInertiaRequests.php @@ -5,7 +5,6 @@ use Illuminate\Foundation\Inspiring; use Illuminate\Http\Request; use Inertia\Middleware; -use Tighten\Ziggy\Ziggy; class HandleInertiaRequests extends Middleware { @@ -46,10 +45,6 @@ public function share(Request $request): array 'auth' => [ 'user' => $request->user(), ], - 'ziggy' => fn (): array => [ - ...(new Ziggy)->toArray(), - 'location' => $request->url(), - ], 'sidebarOpen' => ! $request->hasCookie('sidebar_state') || $request->cookie('sidebar_state') === 'true', ]; } diff --git a/composer.json b/composer.json index d33ae8c47..6bf29e23c 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,7 @@ "inertiajs/inertia-laravel": "^2.0", "laravel/framework": "^12.0", "laravel/tinker": "^2.10.1", - "tightenco/ziggy": "^2.4" + "laravel/wayfinder": "^0.1.6" }, "require-dev": { "fakerphp/faker": "^1.23", diff --git a/package-lock.json b/package-lock.json index 72687b17f..2af0b95e0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -40,6 +40,7 @@ }, "devDependencies": { "@eslint/js": "^9.19.0", + "@laravel/vite-plugin-wayfinder": "^0.1.3", "@types/node": "^22.13.5", "eslint": "^9.17.0", "eslint-config-prettier": "^10.0.1", @@ -1112,6 +1113,13 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@laravel/vite-plugin-wayfinder": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@laravel/vite-plugin-wayfinder/-/vite-plugin-wayfinder-0.1.3.tgz", + "integrity": "sha512-S/21Lzl7lci7LrRo/VsN5AXT02AMf7rs+OPTyt3VPgffBB1wTrzwsPr28sCU0gcR/APhfC1eVIUwpLbAvBmyKw==", + "dev": true, + "license": "MIT" + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", diff --git a/package.json b/package.json index 7327bd34b..d30f1da21 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ }, "devDependencies": { "@eslint/js": "^9.19.0", + "@laravel/vite-plugin-wayfinder": "^0.1.3", "@types/node": "^22.13.5", "eslint": "^9.17.0", "eslint-config-prettier": "^10.0.1", diff --git a/resources/js/components/delete-user.tsx b/resources/js/components/delete-user.tsx index e1f8788bb..87ec25b4d 100644 --- a/resources/js/components/delete-user.tsx +++ b/resources/js/components/delete-user.tsx @@ -9,15 +9,16 @@ import { Label } from '@/components/ui/label'; import HeadingSmall from '@/components/heading-small'; import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogTitle, DialogTrigger } from '@/components/ui/dialog'; +import { destroy } from '@/actions/App/Http/Controllers/Settings/ProfileController'; export default function DeleteUser() { const passwordInput = useRef(null); - const { data, setData, delete: destroy, processing, reset, errors, clearErrors } = useForm>({ password: '' }); + const { data, setData, submit, processing, reset, errors, clearErrors } = useForm>({ password: '' }); const deleteUser: FormEventHandler = (e) => { e.preventDefault(); - destroy(route('profile.destroy'), { + submit(destroy(), { preserveScroll: true, onSuccess: () => closeModal(), onError: () => passwordInput.current?.focus(), diff --git a/resources/js/components/user-menu-content.tsx b/resources/js/components/user-menu-content.tsx index c002b1947..76112ef5c 100644 --- a/resources/js/components/user-menu-content.tsx +++ b/resources/js/components/user-menu-content.tsx @@ -4,6 +4,8 @@ import { useMobileNavigation } from '@/hooks/use-mobile-navigation'; import { type User } from '@/types'; import { Link, router } from '@inertiajs/react'; import { LogOut, Settings } from 'lucide-react'; +import { edit } from '@/routes/profile'; +import { logout } from '@/routes'; interface UserMenuContentProps { user: User; @@ -27,7 +29,7 @@ export function UserMenuContent({ user }: UserMenuContentProps) { - + Settings @@ -35,7 +37,7 @@ export function UserMenuContent({ user }: UserMenuContentProps) { - + Log out diff --git a/resources/js/layouts/auth/auth-card-layout.tsx b/resources/js/layouts/auth/auth-card-layout.tsx index d0bfc4e08..395dd862b 100644 --- a/resources/js/layouts/auth/auth-card-layout.tsx +++ b/resources/js/layouts/auth/auth-card-layout.tsx @@ -2,6 +2,7 @@ import AppLogoIcon from '@/components/app-logo-icon'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Link } from '@inertiajs/react'; import { type PropsWithChildren } from 'react'; +import { home } from '@/routes'; export default function AuthCardLayout({ children, @@ -15,7 +16,7 @@ export default function AuthCardLayout({ return (
- +
diff --git a/resources/js/layouts/auth/auth-simple-layout.tsx b/resources/js/layouts/auth/auth-simple-layout.tsx index 6de3efcd8..5613df6f9 100644 --- a/resources/js/layouts/auth/auth-simple-layout.tsx +++ b/resources/js/layouts/auth/auth-simple-layout.tsx @@ -1,6 +1,7 @@ import AppLogoIcon from '@/components/app-logo-icon'; import { Link } from '@inertiajs/react'; import { type PropsWithChildren } from 'react'; +import { home } from '@/routes'; interface AuthLayoutProps { name?: string; @@ -14,7 +15,7 @@ export default function AuthSimpleLayout({ children, title, description }: Props
- +
diff --git a/resources/js/layouts/auth/auth-split-layout.tsx b/resources/js/layouts/auth/auth-split-layout.tsx index 03daf1c0d..7baeadca3 100644 --- a/resources/js/layouts/auth/auth-split-layout.tsx +++ b/resources/js/layouts/auth/auth-split-layout.tsx @@ -2,6 +2,7 @@ import AppLogoIcon from '@/components/app-logo-icon'; import { type SharedData } from '@/types'; import { Link, usePage } from '@inertiajs/react'; import { type PropsWithChildren } from 'react'; +import { home } from '@/routes'; interface AuthLayoutProps { title?: string; @@ -15,7 +16,7 @@ export default function AuthSplitLayout({ children, title, description }: PropsW
- + {name} @@ -30,7 +31,7 @@ export default function AuthSplitLayout({ children, title, description }: PropsW
- +
diff --git a/resources/js/pages/auth/confirm-password.tsx b/resources/js/pages/auth/confirm-password.tsx index bc1ae5723..b8c9353b7 100644 --- a/resources/js/pages/auth/confirm-password.tsx +++ b/resources/js/pages/auth/confirm-password.tsx @@ -8,16 +8,17 @@ import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import AuthLayout from '@/layouts/auth-layout'; +import { store } from '@/actions/App/Http/Controllers/Auth/ConfirmablePasswordController'; export default function ConfirmPassword() { - const { data, setData, post, processing, errors, reset } = useForm>({ + const { data, setData, submit, processing, errors, reset } = useForm>({ password: '', }); - const submit: FormEventHandler = (e) => { + const submitForm: FormEventHandler = (e) => { e.preventDefault(); - post(route('password.confirm'), { + submit(store(), { onFinish: () => reset('password'), }); }; @@ -29,7 +30,7 @@ export default function ConfirmPassword() { > -
+
diff --git a/resources/js/pages/auth/forgot-password.tsx b/resources/js/pages/auth/forgot-password.tsx index 86d1b3069..20f8666bc 100644 --- a/resources/js/pages/auth/forgot-password.tsx +++ b/resources/js/pages/auth/forgot-password.tsx @@ -9,16 +9,18 @@ import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import AuthLayout from '@/layouts/auth-layout'; +import { store } from '@/actions/App/Http/Controllers/Auth/PasswordResetLinkController'; +import { login } from '@/routes'; export default function ForgotPassword({ status }: { status?: string }) { - const { data, setData, post, processing, errors } = useForm>({ + const { data, setData, submit, processing, errors } = useForm>({ email: '', }); - const submit: FormEventHandler = (e) => { + const submitForm: FormEventHandler = (e) => { e.preventDefault(); - post(route('password.email')); + submit(store()); }; return ( @@ -28,7 +30,7 @@ export default function ForgotPassword({ status }: { status?: string }) { {status &&
{status}
}
- +
Or, return to - log in + log in
diff --git a/resources/js/pages/auth/login.tsx b/resources/js/pages/auth/login.tsx index 28f76f08b..d519f6a40 100644 --- a/resources/js/pages/auth/login.tsx +++ b/resources/js/pages/auth/login.tsx @@ -9,6 +9,9 @@ import { Checkbox } from '@/components/ui/checkbox'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import AuthLayout from '@/layouts/auth-layout'; +import { store } from '@/actions/App/Http/Controllers/Auth/AuthenticatedSessionController'; +import { register } from '@/routes'; +import { request } from '@/routes/password'; type LoginForm = { email: string; @@ -22,15 +25,15 @@ interface LoginProps { } export default function Login({ status, canResetPassword }: LoginProps) { - const { data, setData, post, processing, errors, reset } = useForm>({ + const { data, setData, submit, processing, errors, reset } = useForm>({ email: '', password: '', remember: false, }); - const submit: FormEventHandler = (e) => { + const submitForm: FormEventHandler = (e) => { e.preventDefault(); - post(route('login'), { + submit(store(), { onFinish: () => reset('password'), }); }; @@ -39,7 +42,7 @@ export default function Login({ status, canResetPassword }: LoginProps) { - +
@@ -61,7 +64,7 @@ export default function Login({ status, canResetPassword }: LoginProps) {
{canResetPassword && ( - + Forgot password? )} @@ -98,7 +101,7 @@ export default function Login({ status, canResetPassword }: LoginProps) {
Don't have an account?{' '} - + Sign up
diff --git a/resources/js/pages/auth/register.tsx b/resources/js/pages/auth/register.tsx index 6b0faa8c1..926a6110a 100644 --- a/resources/js/pages/auth/register.tsx +++ b/resources/js/pages/auth/register.tsx @@ -8,6 +8,8 @@ import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import AuthLayout from '@/layouts/auth-layout'; +import { store } from '@/actions/App/Http/Controllers/Auth/RegisteredUserController'; +import { login } from '@/routes'; type RegisterForm = { name: string; @@ -17,16 +19,16 @@ type RegisterForm = { }; export default function Register() { - const { data, setData, post, processing, errors, reset } = useForm>({ + const { data, setData, submit, processing, errors, reset } = useForm>({ name: '', email: '', password: '', password_confirmation: '', }); - const submit: FormEventHandler = (e) => { + const submitForm: FormEventHandler = (e) => { e.preventDefault(); - post(route('register'), { + submit(store(), { onFinish: () => reset('password', 'password_confirmation'), }); }; @@ -34,7 +36,7 @@ export default function Register() { return ( - +
@@ -109,7 +111,7 @@ export default function Register() {
Already have an account?{' '} - + Log in
diff --git a/resources/js/pages/auth/reset-password.tsx b/resources/js/pages/auth/reset-password.tsx index 8ea53031f..11f35d720 100644 --- a/resources/js/pages/auth/reset-password.tsx +++ b/resources/js/pages/auth/reset-password.tsx @@ -7,6 +7,7 @@ import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import AuthLayout from '@/layouts/auth-layout'; +import { store } from '@/actions/App/Http/Controllers/Auth/NewPasswordController'; interface ResetPasswordProps { token: string; @@ -21,16 +22,16 @@ type ResetPasswordForm = { }; export default function ResetPassword({ token, email }: ResetPasswordProps) { - const { data, setData, post, processing, errors, reset } = useForm>({ + const { data, setData, submit, processing, errors, reset } = useForm>({ token: token, email: email, password: '', password_confirmation: '', }); - const submit: FormEventHandler = (e) => { + const submitForm: FormEventHandler = (e) => { e.preventDefault(); - post(route('password.store'), { + submit(store(), { onFinish: () => reset('password', 'password_confirmation'), }); }; @@ -39,7 +40,7 @@ export default function ResetPassword({ token, email }: ResetPasswordProps) { - +
diff --git a/resources/js/pages/auth/verify-email.tsx b/resources/js/pages/auth/verify-email.tsx index b4f7846b7..d1d6e6c82 100644 --- a/resources/js/pages/auth/verify-email.tsx +++ b/resources/js/pages/auth/verify-email.tsx @@ -6,14 +6,16 @@ import { FormEventHandler } from 'react'; import TextLink from '@/components/text-link'; import { Button } from '@/components/ui/button'; import AuthLayout from '@/layouts/auth-layout'; +import { send } from '@/routes/verification'; +import { logout } from '@/routes'; export default function VerifyEmail({ status }: { status?: string }) { - const { post, processing } = useForm({}); + const { submit, processing } = useForm({}); - const submit: FormEventHandler = (e) => { + const submitForm: FormEventHandler = (e) => { e.preventDefault(); - post(route('verification.send')); + submit(send()); }; return ( @@ -26,13 +28,13 @@ export default function VerifyEmail({ status }: { status?: string }) {
)} - + - + Log out diff --git a/resources/js/pages/settings/password.tsx b/resources/js/pages/settings/password.tsx index 43540bb1b..0d8b4df82 100644 --- a/resources/js/pages/settings/password.tsx +++ b/resources/js/pages/settings/password.tsx @@ -10,6 +10,7 @@ import HeadingSmall from '@/components/heading-small'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; +import { update } from '@/actions/App/Http/Controllers/Settings/PasswordController'; const breadcrumbs: BreadcrumbItem[] = [ { @@ -22,7 +23,7 @@ export default function Password() { const passwordInput = useRef(null); const currentPasswordInput = useRef(null); - const { data, setData, errors, put, reset, processing, recentlySuccessful } = useForm({ + const { data, setData, errors, submit, reset, processing, recentlySuccessful } = useForm({ current_password: '', password: '', password_confirmation: '', @@ -31,7 +32,7 @@ export default function Password() { const updatePassword: FormEventHandler = (e) => { e.preventDefault(); - put(route('password.update'), { + submit(update(), { preserveScroll: true, onSuccess: () => reset(), onError: (errors) => { diff --git a/resources/js/pages/settings/profile.tsx b/resources/js/pages/settings/profile.tsx index 3aeed3a7b..f044458cd 100644 --- a/resources/js/pages/settings/profile.tsx +++ b/resources/js/pages/settings/profile.tsx @@ -11,6 +11,8 @@ import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import AppLayout from '@/layouts/app-layout'; import SettingsLayout from '@/layouts/settings/layout'; +import { update } from '@/actions/App/Http/Controllers/Settings/ProfileController'; +import { send } from '@/routes/verification'; const breadcrumbs: BreadcrumbItem[] = [ { @@ -27,15 +29,15 @@ type ProfileForm = { export default function Profile({ mustVerifyEmail, status }: { mustVerifyEmail: boolean; status?: string }) { const { auth } = usePage().props; - const { data, setData, patch, errors, processing, recentlySuccessful } = useForm>({ + const { data, setData, submit, errors, processing, recentlySuccessful } = useForm>({ name: auth.user.name, email: auth.user.email, }); - const submit: FormEventHandler = (e) => { + const submitForm: FormEventHandler = (e) => { e.preventDefault(); - patch(route('profile.update'), { + submit(update(), { preserveScroll: true, }); }; @@ -48,7 +50,7 @@ export default function Profile({ mustVerifyEmail, status }: { mustVerifyEmail:
-
+
@@ -87,7 +89,7 @@ export default function Profile({ mustVerifyEmail, status }: { mustVerifyEmail:

Your email address is unverified.{' '} ().props; @@ -15,7 +16,7 @@ export default function Welcome() {